private float getVolumeData(float[] data, HAPI_VolumeInfo volume, float delta, int x, int y, int z)
    {
        if (x < 0 || x >= volume.tileSize ||
            y < 0 || y >= volume.tileSize ||
            z < 0 || z >= volume.tileSize)
        {
            return(0.0f);
        }

        int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;

        if (data[index] > delta)
        {
            return(1.0f);
        }
        else if (data[index] < -delta)
        {
            return(-1.0f);
        }
        else
        {
            return(0.0f);
        }
    }
Пример #2
0
	// CURVES ---------------------------------------------------------------------------------------------------

	public static HAPI_CurveInfo getCurveInfo(
		HAPI_AssetId asset_id, HAPI_ObjectId object_id, HAPI_GeoId geo_id, HAPI_PartId part_id,
		ref HAPI_VolumeInfo volume_info )
	{
#if ( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) )
		HAPI_CurveInfo curve_info = new HAPI_CurveInfo();
		HAPI_Result status_code = HAPI_GetCurveInfo( ref mySession, asset_id, object_id, geo_id, part_id, ref curve_info );
		processStatusCode( status_code );
		return curve_info;
#else
		throw new HoudiniErrorUnsupportedPlatform();
#endif
	}
    private void createSurfaceVolume(GameObject node, float[] data, HAPI_VolumeTileInfo tile, HAPI_VolumeInfo volume)
    {
        // Create a particle with alpha = to the data format
        const float particle_epsilon = 0.05f;
        int         particle_count   = 0;

        for (int i = 0; i < data.Length; ++i)
        {
            if (data[i] > -particle_epsilon && data[i] < particle_epsilon)
            {
                particle_count++;
            }
        }

        MeshFilter   mesh_filter   = HoudiniControl.getOrCreateComponent <MeshFilter>(node);
        MeshRenderer mesh_renderer = HoudiniControl.getOrCreateComponent <MeshRenderer>(node);

        if (!mesh_filter.sharedMesh)
        {
            mesh_filter.sharedMesh = new Mesh();
        }
        mesh_filter.sharedMesh.Clear();

        if (particle_count <= 0)
        {
            return;
        }

        if (!mesh_renderer.sharedMaterial)
        {
            mesh_renderer.sharedMaterial = new Material(Shader.Find("Houdini/VolumeSurface"));
        }
        mesh_renderer.sharedMaterial.SetFloat("_PointSize", 70.0f);
        mesh_renderer.sharedMaterial.SetColor("_Color", new Color(1.0f, 0.9f, 0.9f));

        Vector3[] vertices = new Vector3[particle_count];
        Color[]   colors   = new Color[particle_count];
        Vector3[] normals  = new Vector3[particle_count];
        Vector2[] uvs      = new Vector2[particle_count];

        // Create the selection indices.
        int[] indices = new int[vertices.Length];
        for (int i = 0; i < vertices.Length; ++i)
        {
            indices[i] = i;
        }

        Vector3 tileMin = new Vector3(tile.minX, tile.minY, tile.minZ);
        //float volume_scale = volume.transform.scale[ 0 ] * 2.0f;
        int part_index = 0;

        for (int z = 0; z < volume.tileSize; ++z)
        {
            for (int y = 0; y < volume.tileSize; ++y)
            {
                for (int x = 0; x < volume.tileSize; ++x)
                {
                    int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;
                    if (data[index] > -particle_epsilon && data[index] < particle_epsilon &&
                        part_index < particle_count)
                    {
                        // Get particle position.
                        Vector3 pos = new Vector3((float)x, (float)y, (float)z);
                        pos = 1.2f * ((pos + tileMin) - new Vector3(0.5f, 0.5f, 0.5f));
                        vertices[part_index] = node.transform.parent.TransformPoint(pos);

                        // Get particle normal.
                        int     amount         = 1;
                        int     sample_count   = 0;
                        Vector3 average_normal = Vector3.zero;
                        for (int xi = -1; xi <= 1; ++xi)
                        {
                            for (int yi = -1; yi <= 1; ++yi)
                            {
                                for (int zi = -1; zi <= 1; ++zi)
                                {
                                    if (xi == 0 && yi == 0 && zi == 0)
                                    {
                                        continue;
                                    }

                                    float result = getVolumeData(data, volume, particle_epsilon, x + xi * amount, y + yi * amount, z + zi * amount);

                                    Vector3 normal = Vector3.zero;
                                    if (result < -0.5f)
                                    {
                                        normal = new Vector3(-xi, -yi, -zi);
                                    }
                                    else if (result > 0.5f)
                                    {
                                        normal = new Vector3(xi, yi, zi);
                                    }
                                    else
                                    {
                                        continue;
                                    }

                                    average_normal += normal;
                                    sample_count++;
                                }
                            }
                        }
                        average_normal /= sample_count;
                        average_normal.Normalize();
                        normals[part_index] = average_normal;

                        // Get particle color.
                        average_normal.x  += 1.0f; average_normal.y += 1.0f; average_normal.z += 1.0f;
                        average_normal    /= 2.0f;
                        colors[part_index] = new Color(average_normal.x, average_normal.y, average_normal.z, 1);

                        part_index++;
                    }
                }
            }
        }

        mesh_filter.sharedMesh.vertices = vertices;
        mesh_filter.sharedMesh.colors   = colors;
        mesh_filter.sharedMesh.normals  = normals;
        mesh_filter.sharedMesh.uv       = uvs;
        mesh_filter.sharedMesh.SetIndices(indices, MeshTopology.Points, 0);
    }
    private void createFogVolume(GameObject node, float[] data, HAPI_VolumeTileInfo tile, HAPI_VolumeInfo volume)
    {
        // Create a particle with alpha = to the data format
        const float particle_epsilon = 0.0f;
        int         nparticles       = 0;

        for (int i = 0; i < data.Length; ++i)
        {
            if (data[i] > particle_epsilon)
            {
                nparticles++;
            }
        }
        if (nparticles == 0)
        {
            DestroyImmediate(node);
            return;
        }

#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
        ParticleEmitter particle_emitter = node.AddComponent("EllipsoidParticleEmitter") as ParticleEmitter;
#else
        ParticleEmitter particle_emitter = node.AddComponent <EllipsoidParticleEmitter>() as ParticleEmitter;
#endif // UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
        particle_emitter.emit    = false;
        particle_emitter.maxSize = volume.transform.scale[0] * 2;
        particle_emitter.minSize = volume.transform.scale[1] * 2;
        particle_emitter.ClearParticles();
        particle_emitter.Emit(nparticles);

        Vector3    tileMin    = new Vector3(tile.minX, tile.minY, tile.minZ);
        int        part_index = 0;
        Particle[] particles  = particle_emitter.particles;
        for (int z = 0; z < volume.tileSize; ++z)
        {
            for (int y = 0; y < volume.tileSize; ++y)
            {
                for (int x = 0; x < volume.tileSize; ++x)
                {
                    int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;
                    if (data[index] > particle_epsilon &&
                        part_index < particles.Length)
                    {
                        Vector3 pos = new Vector3((float)x, (float)y, (float)z);
                        pos = 2 * ((pos + tileMin) - new Vector3(0.5f, 0.5f, 0.5f));

                        particles[part_index].position =
                            node.transform.parent.TransformPoint(pos);
                        particles[part_index].color =
                            new Color(data[index], data[index], data[index], data[index]);
                        part_index++;
                    }
                }
            }
        }
        particle_emitter.particles = particles;

        ParticleRenderer renderer = node.GetComponent <ParticleRenderer>();
        if (renderer == null)
        {
            renderer = node.AddComponent <ParticleRenderer>();
        }

        renderer.material = createSoftCircle(
            new Color(Random.Range(0.5f, 1.0f), Random.Range(0.5f, 1.0f), Random.Range(0.5f, 1.0f)));
    }
Пример #5
0
    private float getVolumeData( float[] data, HAPI_VolumeInfo volume, float delta, int x, int y, int z )
    {
        if ( x < 0 || x >= volume.tileSize
            || y < 0 || y >= volume.tileSize
            || z < 0 || z >= volume.tileSize )
            return 0.0f;

        int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;

        if ( data[ index ] > delta )
            return 1.0f;
        else if ( data[ index ] < -delta )
            return -1.0f;
        else
            return 0.0f;
    }
    public void refresh(bool reload_asset, bool has_geo_changed, bool has_material_changed)
    {
        if (prGeoControl == null)
        {
            Debug.LogError("Why is my geo control null on a refresh?");
            return;
        }

        GameObject part_node = gameObject;

        // Get Part info.
        HAPI_PartInfo part_info = new HAPI_PartInfo();

        HoudiniHost.getPartInfo(prAssetId, prObjectId, prGeoId, prPartId, out part_info);

        bool is_empty = part_info.vertexCount <= 0 && part_info.pointCount <= 0;
        bool is_mesh  = (part_info.vertexCount > 0);

        // For Debugging.
#if false
        Debug.Log("ATTRIBS");
        HoudiniAssetUtility.printAllAttributeNames(prAssetId, prObjectId, prGeoId, prPartId);
        Debug.Log("GROUPS");
        HoudiniAssetUtility.printAllGroups(prAssetId, prObjectId, prGeoId, prPartId);
        Debug.Log("DONE");
        Debug.Log("");
#endif

        // TODO: Make this info a permanent UI display.
        //if ( prEnableLogging && ( reload_asset || has_geo_changed || has_material_changed ) )
        //	Debug.Log( "Obj #" + part_control.prObjectId + " (" + part_control.prObjectName + "): "
        //			   + "verts: " + part_info.vertexCount + " faces: " + part_info.faceCount );

        if (reload_asset || has_geo_changed)
        {
            // Initialize our part control.
            init(-1, part_info.id, part_info.name);

            // Overwrite name.
            part_node.name = part_info.name;

            if (is_empty)
            {
                // Add required components.
                MeshFilter mesh_filter = getOrCreateComponent <MeshFilter>();

                // Get or create mesh.
                Mesh part_mesh = mesh_filter.sharedMesh;
                if (part_mesh == null)
                {
                    mesh_filter.mesh = new Mesh();
                    part_mesh        = mesh_filter.sharedMesh;
                }
                part_mesh.Clear();
            }
            else if (is_mesh)               // Valid mesh.
            {
                // Add required components.
                MeshFilter mesh_filter = getOrCreateComponent <MeshFilter>();

                // Get or create mesh.
                Mesh part_mesh = mesh_filter.sharedMesh;
                if (part_mesh == null)
                {
                    mesh_filter.mesh = new Mesh();
                    part_mesh        = mesh_filter.sharedMesh;
                }
                part_mesh.Clear();

                // Get mesh.
                try
                {
                    HoudiniAssetUtility.getMesh(
                        this, part_mesh, prAsset.prGenerateTangents && HoudiniHost.prGenerateTangents);
                }
                catch (HoudiniErrorIgnorable) {}
                catch (HoudiniError error)
                {
                    Debug.LogWarning(error.ToString());
                    return;
                }

                // Add collider if group name matches. (Should be added after the mesh is set so that it
                // picks up the mesh automagically)
                if (part_info.name.Contains(HoudiniHost.prRenderedCollisionGroupName))
                {
                    MeshCollider mesh_collider = getOrCreateComponent <MeshCollider>();
                    getOrCreateComponent <MeshRenderer>();
                    mesh_collider.enabled = false;
                    mesh_collider.enabled = true;
                }
                else if (part_info.name.Contains(HoudiniHost.prCollisionGroupName))
                {
                    MeshCollider mesh_collider = getOrCreateComponent <MeshCollider>();
                    mesh_collider.enabled = false;
                    mesh_collider.enabled = true;
                }
                else
                {
                    getOrCreateComponent <MeshRenderer>();
                }

#if !HAPI_PAINT_SUPPORT
                if (myGeoControl.prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE)
                {
                    MeshRenderer mesh_renderer = getOrCreateComponent <MeshRenderer>();
                    MeshCollider mesh_collider = getOrCreateComponent <MeshCollider>();
                    if (myGeoControl.prGeoAttributeManager)
                    {
                        myGeoControl.prGeoAttributeManager.reInit(
                            part_mesh, mesh_renderer, mesh_collider, transform);
                    }
                    mesh_collider.enabled = false;
                    mesh_collider.enabled = true;
                }
#endif // !HAPI_PAINT_SUPPORT

                // Add Mesh-to-Prefab component.
                HoudiniMeshToPrefab mesh_saver = getOrCreateComponent <HoudiniMeshToPrefab>();
                mesh_saver.prGameObject = part_node;
                mesh_saver.prMeshName   = prAsset.prAssetName + "_" + part_node.name;
            }
            else if (HoudiniHost.prEnablePointsAsParticles && part_info.vertexCount <= 0 && part_info.pointCount > 0)               // Particles?
            {
                // Get position attributes.
                HAPI_AttributeInfo pos_attr_info = new HAPI_AttributeInfo(HoudiniConstants.HAPI_ATTRIB_POSITION);
                float[]            pos_attr      = new float[0];
                HoudiniAssetUtility.getAttribute(
                    prAssetId, prObjectId, prGeoId, prPartId, 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.");
                }
                else if (pos_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT)
                {
                    throw new HoudiniErrorIgnorable("I only understand position as point attributes!");
                }

                // Get colour attributes.
                HAPI_AttributeInfo colour_attr_info = new HAPI_AttributeInfo(HoudiniConstants.HAPI_ATTRIB_COLOR);
                float[]            colour_attr      = new float[0];
                HoudiniAssetUtility.getAttribute(
                    prAssetId, prObjectId, prGeoId, prPartId, HoudiniConstants.HAPI_ATTRIB_COLOR,
                    ref colour_attr_info, ref colour_attr, HoudiniHost.getAttributeFloatData);

                ParticleEmitter particle_emitter = part_node.GetComponent <ParticleEmitter>();
                if (particle_emitter == null)
                {
#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
                    particle_emitter = part_node.AddComponent("EllipsoidParticleEmitter") as ParticleEmitter;
#else
                    particle_emitter = part_node.AddComponent <EllipsoidParticleEmitter>() as ParticleEmitter;
#endif // UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
                }
                particle_emitter.ClearParticles();

                particle_emitter.emit          = false;
                particle_emitter.useWorldSpace = true;

                particle_emitter.maxSize = 0.06f;
                particle_emitter.minSize = 0.02f;

                ParticleRenderer renderer = getOrCreateComponent <ParticleRenderer>();
                Material         mat      = new Material(Shader.Find("Particles/Additive (Soft)"));
                int       width           = 20;
                int       length          = 20;
                Texture2D tex             = new Texture2D(width, length, TextureFormat.RGBA32, false);
                for (int x = 0; x < width; ++x)
                {
                    for (int y = 0; y < length; ++y)
                    {
                        float dist = (x - 10) * (x - 10) + (y - 10) * (y - 10);
                        dist = Mathf.Sqrt(dist);
                        float alpha_f = 1.0f - dist / 10.0f;
                        Color col     = new Color(0.8f, 0.8f, 0.8f, alpha_f);
                        tex.SetPixel(x, y, col);
                    }
                }
                tex.Apply();
                mat.mainTexture   = tex;
                mat.color         = new Color(1.0f, 1.0f, 0.5f);
                renderer.material = mat;

                particle_emitter.Emit(part_info.pointCount);

                Particle[] particles = particle_emitter.particles;

                if (particle_emitter.particles.Length < part_info.pointCount)
                {
                    Debug.LogWarning("Geo has too many particles. Expected less than "
                                     + particle_emitter.particles.Length
                                     + " but found " + part_info.pointCount + ". "
                                     + " Only using the first "
                                     + particle_emitter.particles.Length + ".");
                }


                for (int i = 0; i < particle_emitter.particles.Length; ++i)
                {
                    particles[i].position = new Vector3(pos_attr[i * 3 + 0],
                                                        pos_attr[i * 3 + 1],
                                                        pos_attr[i * 3 + 2]);
                    if (colour_attr_info.exists && colour_attr_info.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_POINT)
                    {
                        float alpha =
                            colour_attr_info.tupleSize == 4
                                                                ? colour_attr[i * colour_attr_info.tupleSize + 3]
                                                                : 1.0f;
                        particles[i].color = new Color(colour_attr[i * colour_attr_info.tupleSize + 0],
                                                       colour_attr[i * colour_attr_info.tupleSize + 1],
                                                       colour_attr[i * colour_attr_info.tupleSize + 2],
                                                       alpha);
                    }
                }

                particle_emitter.particles = particles;
            }

            if (part_info.hasVolume)
            {
                // Clear previous volume tiles.
                destroyChildren(part_node.transform);

                // If we have a volume, retrieve the volume info
                HAPI_VolumeInfo volume = new HAPI_VolumeInfo();
                HoudiniHost.getVolumeInfo(prAssetId, prObjectId, prGeoId, prPartId, ref volume);

                // The volume.transform.scale is the voxel size. Both the particle
                // delta and the point size are affected by the voxel size.
                HoudiniAssetUtility.applyTransform(volume.transform, part_node.transform);
                float particle_delta = HoudiniConstants.HAPI_VOLUME_SURFACE_DELTA_MULT * Mathf.Max(Mathf.Max(
                                                                                                       volume.transform.scale[0],
                                                                                                       volume.transform.scale[1]),
                                                                                                   volume.transform.scale[2]);
                float point_size = HoudiniConstants.HAPI_VOLUME_SURFACE_PT_SIZE_MULT * particle_delta;

                List <Vector3> acc_vertices = new List <Vector3>();
                List <Vector3> acc_normals  = new List <Vector3>();

                float[] values     = new float[volume.tileSize * volume.tileSize * volume.tileSize];
                int     tile_index = 0;
                int     current_container_particle_index = 0;

                // Iterate through the voxels and print out the data, for now.
                HAPI_VolumeTileInfo tile = new HAPI_VolumeTileInfo();
                HoudiniHost.getFirstVolumeTile(prAssetId, prObjectId, prGeoId, prPartId, ref tile);
                while (tile.isValid)
                {
                    for (int i = 0; i < values.Length; ++i)
                    {
                        values[i] = 0;
                    }
                    HoudiniHost.getVolumeTileFloatData(
                        prAssetId, prObjectId, prGeoId, prPartId, ref tile, values);

                    Vector3 tileMin    = new Vector3(tile.minX, tile.minY, tile.minZ);
                    int     part_index = 0;
                    for (int z = 0; z < volume.tileSize; ++z)
                    {
                        for (int y = 0; y < volume.tileSize; ++y)
                        {
                            for (int x = 0; x < volume.tileSize; ++x)
                            {
                                int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;
                                if (values[index] > -particle_delta && values[index] < particle_delta)
                                {
                                    // Make sure we have enough room in our arrays.
                                    if (current_container_particle_index
                                        > HoudiniConstants.HAPI_VOLUME_SURFACE_MAX_PT_PER_C)
                                    {
                                        createVolumeTilesObject(
                                            point_size, part_node.transform, acc_vertices, acc_normals);
                                        current_container_particle_index = 0;
                                        acc_vertices.Clear();
                                        acc_normals.Clear();
                                    }

                                    // Get particle position.
                                    Vector3 pos = new Vector3((float)x, (float)y, (float)z);
                                    pos   = HoudiniConstants.HAPI_VOLUME_POSITION_MULT * (pos + tileMin);
                                    pos.x = -pos.x;
                                    acc_vertices.Add(part_node.transform.TransformPoint(pos));

                                    // Get particle normal.
                                    int     amount         = 1;
                                    int     sample_count   = 0;
                                    Vector3 average_normal = Vector3.zero;
                                    for (int xi = -1; xi <= 1; ++xi)
                                    {
                                        for (int yi = -1; yi <= 1; ++yi)
                                        {
                                            for (int zi = -1; zi <= 1; ++zi)
                                            {
                                                if (xi == 0 && yi == 0 && zi == 0)
                                                {
                                                    continue;
                                                }

                                                float result = getVolumeData(
                                                    values, volume, particle_delta, x + xi * amount, y + yi * amount, z + zi * amount);

                                                Vector3 normal = Vector3.zero;
                                                if (result < -0.5f)
                                                {
                                                    normal = new Vector3(-xi, -yi, -zi);
                                                }
                                                else if (result > 0.5f)
                                                {
                                                    normal = new Vector3(xi, yi, zi);
                                                }
                                                else
                                                {
                                                    continue;
                                                }

                                                average_normal += normal;
                                                sample_count++;
                                            }
                                        }
                                    }
                                    average_normal /= sample_count;
                                    average_normal.Normalize();
                                    acc_normals.Add(average_normal);

                                    part_index++;
                                    current_container_particle_index++;
                                }
                            }
                        }
                    }

                    HoudiniHost.getNextVolumeTile(prAssetId, prObjectId, prGeoId, prPartId, ref tile);

                    tile_index++;
                }                 // tile iteration

                // If we have left-over particles in our arrays we need another container.
                createVolumeTilesObject(point_size, part_node.transform, acc_vertices, acc_normals);
            }             // if has volume
            else          // Restore part node if previously used to store volume.
            {
                // Clear previous volume tiles.
                destroyChildren(part_node.transform);
                part_node.transform.localScale    = Vector3.one;
                part_node.transform.localPosition = Vector3.zero;
                part_node.transform.localRotation = Quaternion.identity;
            }
        }

        // Refresh enabled flags.
        if (gameObject.GetComponent <MeshCollider>())
        {
            gameObject.GetComponent <MeshCollider>().enabled =
                prObjectVisible &&
                (prAsset.prIsGeoVisible || prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE);
        }
        if (gameObject.GetComponent <MeshRenderer>())
        {
            gameObject.GetComponent <MeshRenderer>().enabled =
                prObjectVisible &&
                (prAsset.prIsGeoVisible || prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE);
        }

        // Assign materials.
        HoudiniAssetUtility.assignMaterial(this, prAsset, (reload_asset || has_material_changed));

        // Assign unity tag.
        assignUnityTag();
    }
Пример #7
0
    private void createFogVolume( GameObject node, float[] data, HAPI_VolumeTileInfo tile, HAPI_VolumeInfo volume )
    {
        // Create a particle with alpha = to the data format
        const float particle_epsilon = 0.0f;
        int nparticles = 0;
        for ( int i = 0; i < data.Length; ++i )
            if ( data[ i ] > particle_epsilon )
                nparticles++;
        if ( nparticles == 0 )
        {
            DestroyImmediate( node );
            return;
        }

        #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
        ParticleEmitter particle_emitter = node.AddComponent( "EllipsoidParticleEmitter" ) as ParticleEmitter;
        #else
        ParticleEmitter particle_emitter = node.AddComponent< EllipsoidParticleEmitter >() as ParticleEmitter;
        #endif // UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
        particle_emitter.emit = false;
        particle_emitter.maxSize = volume.transform.scale[0]*2;
        particle_emitter.minSize = volume.transform.scale[1]*2;
        particle_emitter.ClearParticles();
        particle_emitter.Emit( nparticles );

        Vector3 tileMin = new Vector3( tile.minX, tile.minY, tile.minZ );
        int part_index = 0;
        Particle[] particles = particle_emitter.particles;
        for ( int z = 0; z < volume.tileSize; ++z )
            for ( int y = 0; y < volume.tileSize; ++y )
                for ( int x = 0; x < volume.tileSize; ++x )
                {
                    int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;
                    if ( data[ index ] > particle_epsilon
                        && part_index < particles.Length )
                    {
                        Vector3 pos = new Vector3( (float)x, (float)y, (float)z );
                        pos = 2 * ( ( pos + tileMin ) - new Vector3( 0.5f, 0.5f, 0.5f ) );

                        particles[ part_index ].position =
                            node.transform.parent.TransformPoint( pos );
                        particles[ part_index ].color =
                            new Color( data[ index ], data[ index ], data[ index ], data[ index ] );
                        part_index++;
                    }
                }
        particle_emitter.particles = particles;

        ParticleRenderer renderer = node.GetComponent< ParticleRenderer >();
        if ( renderer == null )
            renderer = node.AddComponent< ParticleRenderer >();

        renderer.material = createSoftCircle(
            new Color( Random.Range( 0.5f, 1.0f ), Random.Range( 0.5f, 1.0f ), Random.Range( 0.5f, 1.0f ) ) );
    }
Пример #8
0
    private void createSurfaceVolume( GameObject node, float[] data, HAPI_VolumeTileInfo tile, HAPI_VolumeInfo volume )
    {
        // Create a particle with alpha = to the data format
        const float particle_epsilon = 0.05f;
        int particle_count = 0;
        for ( int i = 0; i < data.Length; ++i )
            if ( data[ i ] > -particle_epsilon && data[ i ] < particle_epsilon )
                particle_count++;

        MeshFilter mesh_filter = HoudiniControl.getOrCreateComponent< MeshFilter >( node );
        MeshRenderer mesh_renderer = HoudiniControl.getOrCreateComponent< MeshRenderer >( node );

        if ( !mesh_filter.sharedMesh )
            mesh_filter.sharedMesh = new Mesh();
        mesh_filter.sharedMesh.Clear();

        if ( particle_count <= 0 )
            return;

        if ( !mesh_renderer.sharedMaterial )
            mesh_renderer.sharedMaterial = new Material( Shader.Find( "Houdini/VolumeSurface" ) );
        mesh_renderer.sharedMaterial.SetFloat( "_PointSize", 70.0f );
        mesh_renderer.sharedMaterial.SetColor( "_Color", new Color( 1.0f, 0.9f, 0.9f ) );

        Vector3[] vertices = new Vector3[ particle_count ];
        Color[] colors = new Color[ particle_count ];
        Vector3[] normals = new Vector3[ particle_count ];
        Vector2[] uvs = new Vector2[ particle_count ];

        // Create the selection indices.
        int[] indices = new int[ vertices.Length ];
        for ( int i = 0; i < vertices.Length; ++i )
            indices[ i ] = i;

        Vector3 tileMin = new Vector3( tile.minX, tile.minY, tile.minZ );
        //float volume_scale = volume.transform.scale[ 0 ] * 2.0f;
        int part_index = 0;
        for ( int z = 0; z < volume.tileSize; ++z )
            for ( int y = 0; y < volume.tileSize; ++y )
                for ( int x = 0; x < volume.tileSize; ++x )
                {
                    int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;
                    if ( data[ index ] > -particle_epsilon && data[ index ] < particle_epsilon
                        && part_index < particle_count )
                    {
                        // Get particle position.
                        Vector3 pos = new Vector3( (float) x, (float) y, (float) z );
                        pos = 1.2f * ( ( pos + tileMin ) - new Vector3( 0.5f, 0.5f, 0.5f ) );
                        vertices[ part_index ] = node.transform.parent.TransformPoint( pos );

                        // Get particle normal.
                        int amount = 1;
                        int sample_count = 0;
                        Vector3 average_normal = Vector3.zero;
                        for ( int xi = -1; xi <= 1; ++xi )
                            for ( int yi = -1; yi <= 1; ++yi )
                                for ( int zi = -1; zi <= 1; ++zi )
                                {
                                    if ( xi == 0 && yi == 0 && zi == 0 )
                                        continue;

                                    float result = getVolumeData( data, volume, particle_epsilon, x + xi * amount, y + yi * amount, z + zi * amount );

                                    Vector3 normal = Vector3.zero;
                                    if ( result < -0.5f )
                                        normal = new Vector3( -xi, -yi, -zi );
                                    else if ( result > 0.5f )
                                        normal = new Vector3( xi, yi, zi );
                                    else
                                        continue;

                                    average_normal += normal;
                                    sample_count++;
                                }
                        average_normal /= sample_count;
                        average_normal.Normalize();
                        normals[ part_index ] = average_normal;

                        // Get particle color.
                        average_normal.x += 1.0f; average_normal.y += 1.0f; average_normal.z += 1.0f;
                        average_normal /= 2.0f;
                        colors[ part_index ] = new Color( average_normal.x, average_normal.y, average_normal.z, 1 );

                        part_index++;
                    }
                }

        mesh_filter.sharedMesh.vertices = vertices;
        mesh_filter.sharedMesh.colors = colors;
        mesh_filter.sharedMesh.normals = normals;
        mesh_filter.sharedMesh.uv = uvs;
        mesh_filter.sharedMesh.SetIndices( indices, MeshTopology.Points, 0 );
    }
Пример #9
0
    public void refresh( bool reload_asset, bool has_geo_changed, bool has_material_changed )
    {
        if ( prGeoControl == null )
        {
            Debug.LogError( "Why is my geo control null on a refresh?" );
            return;
        }

        GameObject part_node = gameObject;

        // Get Part info.
        HAPI_PartInfo part_info = new HAPI_PartInfo();
        HoudiniHost.getPartInfo( prAssetId, prObjectId, prGeoId, prPartId, out part_info );

        bool is_empty = part_info.vertexCount <= 0 && part_info.pointCount <= 0;
        bool is_mesh = ( part_info.vertexCount > 0 );

        // For Debugging.
        #if false
        Debug.Log( "ATTRIBS" );
            HoudiniAssetUtility.printAllAttributeNames( prAssetId, prObjectId, prGeoId, prPartId );
        Debug.Log( "GROUPS" );
            HoudiniAssetUtility.printAllGroups( prAssetId, prObjectId, prGeoId, prPartId );
        Debug.Log( "DONE" );
        Debug.Log( "" );
        #endif

        // TODO: Make this info a permanent UI display.
        //if ( prEnableLogging && ( reload_asset || has_geo_changed || has_material_changed ) )
        //	Debug.Log( "Obj #" + part_control.prObjectId + " (" + part_control.prObjectName + "): "
        //			   + "verts: " + part_info.vertexCount + " faces: " + part_info.faceCount );

        if ( reload_asset || has_geo_changed )
        {
            // Initialize our part control.
            init( -1, part_info.id, part_info.name );

            // Overwrite name.
            part_node.name = part_info.name;

            if ( is_empty )
            {
                // Add required components.
                MeshFilter mesh_filter = getOrCreateComponent< MeshFilter >();

                // Get or create mesh.
                Mesh part_mesh 				= mesh_filter.sharedMesh;
                if ( part_mesh == null )
                {
                    mesh_filter.mesh 		= new Mesh();
                    part_mesh 				= mesh_filter.sharedMesh;
                }
                part_mesh.Clear();
            }
            else if ( is_mesh ) // Valid mesh.
            {
                // Add required components.
                MeshFilter mesh_filter = getOrCreateComponent< MeshFilter >();

                // Get or create mesh.
                Mesh part_mesh = mesh_filter.sharedMesh;
                if ( part_mesh == null )
                {
                    mesh_filter.mesh = new Mesh();
                    part_mesh = mesh_filter.sharedMesh;
                    part_mesh.name = getAbsolutePath() + "/Mesh";
                }
                part_mesh.Clear();

                // Get mesh.
                try
                {
                    HoudiniAssetUtility.getMesh(
                        this, part_mesh,
                        prAsset.prGenerateUVs,
                        prAsset.prGenerateLightmapUV2s,
                        prAsset.prGenerateTangents );
                }
                catch ( HoudiniErrorIgnorable ) {}
                catch ( HoudiniError error )
                {
                    Debug.LogWarning( error.ToString() );
                    return;
                }

                // Add collider if group name matches. (Should be added after the mesh is set so that it
                // picks up the mesh automagically)
                if ( part_info.name.Contains( HoudiniHost.prRenderedCollisionGroupName ) )
                {
                    MeshCollider mesh_collider = getOrCreateComponent< MeshCollider >();
                    getOrCreateComponent< MeshRenderer >();
                    mesh_collider.enabled = false;
                    mesh_collider.enabled = true;
                }
                else if ( part_info.name.Contains( HoudiniHost.prCollisionGroupName ) )
                {
                    MeshCollider mesh_collider = getOrCreateComponent< MeshCollider >();
                    mesh_collider.enabled = false;
                    mesh_collider.enabled = true;
                }
                else
                {
                    getOrCreateComponent< MeshRenderer >();
                }

                if ( myGeoControl.prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE )
                {
                    MeshRenderer mesh_renderer = getOrCreateComponent< MeshRenderer >();
                    MeshCollider mesh_collider = getOrCreateComponent< MeshCollider >();
                    if ( myGeoControl.prGeoAttributeManager )
                    {
                        myGeoControl.prGeoAttributeManager.reInit(
                            part_mesh, mesh_renderer, mesh_collider, transform );
                    }
                    mesh_collider.enabled = false;
                    mesh_collider.enabled = true;
                }

                // Add Mesh-to-Prefab component.
                HoudiniMeshToPrefab mesh_saver = getOrCreateComponent< HoudiniMeshToPrefab >();
                mesh_saver.prGameObject = part_node;
                mesh_saver.prMeshName = prAsset.prAssetName + "_" + part_node.name;
            }
            else if ( HoudiniHost.prEnablePointsAsParticles && part_info.vertexCount <= 0 && part_info.pointCount > 0 ) // Particles?
            {
                // Get position attributes.
                HAPI_AttributeInfo pos_attr_info = new HAPI_AttributeInfo( HoudiniConstants.HAPI_ATTRIB_POSITION );
                float[] pos_attr = new float[ 0 ];
                HoudiniAssetUtility.getAttribute(
                    prAssetId, prObjectId, prGeoId, prPartId, 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." );
                else if ( pos_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT )
                    throw new HoudiniErrorIgnorable( "I only understand position as point attributes!" );

                // Get colour attributes.
                HAPI_AttributeInfo colour_attr_info = new HAPI_AttributeInfo( HoudiniConstants.HAPI_ATTRIB_COLOR );
                float[] colour_attr = new float[ 0 ];
                HoudiniAssetUtility.getAttribute(
                    prAssetId, prObjectId, prGeoId, prPartId, HoudiniConstants.HAPI_ATTRIB_COLOR,
                    ref colour_attr_info, ref colour_attr, HoudiniHost.getAttributeFloatData );

                ParticleEmitter particle_emitter = part_node.GetComponent< ParticleEmitter >();
                if ( particle_emitter == null )
                {
        #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
                    particle_emitter = part_node.AddComponent( "EllipsoidParticleEmitter" ) as ParticleEmitter;
        #else
                    particle_emitter = part_node.AddComponent< EllipsoidParticleEmitter >() as ParticleEmitter;
        #endif // UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6
                }
                particle_emitter.ClearParticles();

                particle_emitter.emit = false;
                particle_emitter.useWorldSpace = true;

                particle_emitter.maxSize = 0.06f;
                particle_emitter.minSize = 0.02f;

                ParticleRenderer renderer = getOrCreateComponent< ParticleRenderer >();
                Material mat = new Material( Shader.Find( "Particles/Additive (Soft)" ) );
                int width = 20;
                int length = 20;
                Texture2D tex = new Texture2D( width, length, TextureFormat.RGBA32, false );
                for ( int x = 0; x < width; ++x )
                {
                    for ( int y = 0; y < length; ++y )
                    {
                        float dist = (x - 10) * (x-10) + (y-10) * (y-10);
                        dist = Mathf.Sqrt( dist );
                        float alpha_f = 1.0f - dist / 10.0f;
                        Color col = new Color( 0.8f, 0.8f, 0.8f, alpha_f );
                        tex.SetPixel( x, y, col );
                    }
                }
                tex.Apply();
                mat.mainTexture = tex;
                mat.color = new Color( 1.0f, 1.0f, 0.5f );
                renderer.material = mat;

                particle_emitter.Emit( part_info.pointCount );

                Particle[] particles = particle_emitter.particles;

                if ( particle_emitter.particles.Length < part_info.pointCount )
                    Debug.LogWarning( "Geo has too many particles. Expected less than "
                                      + particle_emitter.particles.Length
                                      + " but found " + part_info.pointCount + ". "
                                      + " Only using the first "
                                      + particle_emitter.particles.Length + ".");

                for ( int i = 0; i < particle_emitter.particles.Length; ++i )
                {
                    particles[ i ].position = new Vector3( pos_attr[ i * 3 + 0 ],
                                                           pos_attr[ i * 3 + 1 ],
                                                           pos_attr[ i * 3 + 2 ] );
                    if ( colour_attr_info.exists && colour_attr_info.owner == HAPI_AttributeOwner.HAPI_ATTROWNER_POINT )
                    {
                        float alpha =
                            colour_attr_info.tupleSize == 4
                                ? colour_attr[ i * colour_attr_info.tupleSize + 3 ]
                                : 1.0f;
                        particles[ i ].color = new Color( colour_attr[ i * colour_attr_info.tupleSize + 0 ],
                                                          colour_attr[ i * colour_attr_info.tupleSize + 1 ],
                                                          colour_attr[ i * colour_attr_info.tupleSize + 2 ],
                                                          alpha );
                    }
                }

                particle_emitter.particles = particles;
            }

            if ( part_info.type == HAPI_PartType.HAPI_PARTTYPE_VOLUME )
            {
                // Clear previous volume tiles.
                destroyChildren( part_node.transform );

                // If we have a volume, retrieve the volume info
                HAPI_VolumeInfo volume = new HAPI_VolumeInfo();
                HoudiniHost.getVolumeInfo( prAssetId, prObjectId, prGeoId, prPartId, ref volume );

                // The volume.transform.scale is the voxel size. Both the particle
                // delta and the point size are affected by the voxel size.
                HoudiniAssetUtility.applyTransform( volume.transform, part_node.transform );
                float particle_delta = HoudiniConstants.HAPI_VOLUME_SURFACE_DELTA_MULT * Mathf.Max( Mathf.Max(
                    volume.transform.scale[ 0 ],
                    volume.transform.scale[ 1 ] ),
                    volume.transform.scale[ 2 ] );
                float point_size = HoudiniConstants.HAPI_VOLUME_SURFACE_PT_SIZE_MULT * particle_delta;

                List< Vector3 > acc_vertices = new List< Vector3 >();
                List< Vector3 > acc_normals = new List< Vector3 >();

                float[] values = new float[ volume.tileSize * volume.tileSize * volume.tileSize ];
                int tile_index = 0;
                int current_container_particle_index = 0;

                // Iterate through the voxels and print out the data, for now.
                HAPI_VolumeTileInfo tile = new HAPI_VolumeTileInfo();
                HoudiniHost.getFirstVolumeTile( prAssetId, prObjectId, prGeoId, prPartId, ref tile );
                while ( tile.isValid )
                {
                    for ( int i = 0; i < values.Length; ++i )
                        values[ i ] = 0;
                    HoudiniHost.getVolumeTileFloatData(
                        prAssetId, prObjectId, prGeoId, prPartId, ref tile, values );

                    Vector3 tileMin = new Vector3( tile.minX, tile.minY, tile.minZ );
                    int part_index = 0;
                    for ( int z = 0; z < volume.tileSize; ++z )
                        for ( int y = 0; y < volume.tileSize; ++y )
                            for ( int x = 0; x < volume.tileSize; ++x )
                            {
                                int index = z * volume.tileSize * volume.tileSize + y * volume.tileSize + x;
                                if ( values[ index ] > -particle_delta && values[ index ] < particle_delta )
                                {
                                    // Make sure we have enough room in our arrays.
                                    if ( current_container_particle_index
                                        > HoudiniConstants.HAPI_VOLUME_SURFACE_MAX_PT_PER_C )
                                    {
                                        createVolumeTilesObject(
                                            point_size, part_node.transform, acc_vertices, acc_normals );
                                        current_container_particle_index = 0;
                                        acc_vertices.Clear();
                                        acc_normals.Clear();
                                    }

                                    // Get particle position.
                                    Vector3 pos = new Vector3( (float) x, (float) y, (float) z );
                                    pos = HoudiniConstants.HAPI_VOLUME_POSITION_MULT * ( pos + tileMin );
                                    pos.x = -pos.x;
                                    acc_vertices.Add( part_node.transform.TransformPoint( pos ) );

                                    // Get particle normal.
                                    int amount = 1;
                                    int sample_count = 0;
                                    Vector3 average_normal = Vector3.zero;
                                    for ( int xi = -1; xi <= 1; ++xi )
                                        for ( int yi = -1; yi <= 1; ++yi )
                                            for ( int zi = -1; zi <= 1; ++zi )
                                            {
                                                if ( xi == 0 && yi == 0 && zi == 0 )
                                                    continue;

                                                float result = getVolumeData(
                                                    values, volume, particle_delta, x + xi * amount, y + yi * amount, z + zi * amount );

                                                Vector3 normal = Vector3.zero;
                                                if ( result < -0.5f )
                                                    normal = new Vector3( -xi, -yi, -zi );
                                                else if ( result > 0.5f )
                                                    normal = new Vector3( xi, yi, zi );
                                                else
                                                    continue;

                                                average_normal += normal;
                                                sample_count++;
                                            }
                                    average_normal /= sample_count;
                                    average_normal.Normalize();
                                    acc_normals.Add( average_normal );

                                    part_index++;
                                    current_container_particle_index++;
                                }
                            }

                    HoudiniHost.getNextVolumeTile( prAssetId, prObjectId, prGeoId, prPartId, ref tile );

                    tile_index++;
                } // tile iteration

                // If we have left-over particles in our arrays we need another container.
                createVolumeTilesObject( point_size, part_node.transform, acc_vertices, acc_normals );

            } // if has volume
            else // Restore part node if previously used to store volume.
            {
                // Clear previous volume tiles.
                destroyChildren( part_node.transform );
                part_node.transform.localScale = Vector3.one;
                part_node.transform.localPosition = Vector3.zero;
                part_node.transform.localRotation = Quaternion.identity;
            }
        }

        // Refresh enabled flags.
        {
            bool is_visible = prObjectVisible;
            is_visible &= ( prAsset.prIsGeoVisible || prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE );
            if ( prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE &&
                myGeoControl.prGeoAttributeManager != null )
                is_visible &=
                    myGeoControl.prGeoAttributeManager.prCurrentMode != HoudiniGeoAttributeManager.Mode.NONE;

            if ( gameObject.GetComponent< MeshCollider >() )
                gameObject.GetComponent< MeshCollider >().enabled = is_visible;
            if ( gameObject.GetComponent< MeshRenderer >() )
                gameObject.GetComponent< MeshRenderer >().enabled = is_visible;
        }

        // Assign materials.
        HoudiniAssetUtility.assignMaterial( this, prAsset, reload_asset );

        // Assign unity tag.
        assignUnityTag();
    }
Пример #10
0
	HAPI_SetVolumeInfo(
		ref HAPI_Session session,
		HAPI_AssetId asset_id, HAPI_ObjectId object_id, HAPI_GeoId geo_id,
		ref HAPI_VolumeInfo volume_info );
Пример #11
0
 HAPI_GetVolumeInfo(
     HAPI_AssetId asset_id, HAPI_ObjectId object_id, HAPI_GeoId geo_id, HAPI_PartId part_id,
     ref HAPI_VolumeInfo volume_info);
 HAPI_SetVolumeInfo(
     ref HAPI_Session session,
     HAPI_AssetId asset_id, HAPI_ObjectId object_id, HAPI_GeoId geo_id,
     ref HAPI_VolumeInfo volume_info);
Пример #13
0
    private static extern HAPI_Result HAPI_GetVolumeInfo(
		ref HAPI_Session session,
		HAPI_AssetId asset_id, HAPI_ObjectId object_id, HAPI_GeoId geo_id, HAPI_PartId part_id,
		ref HAPI_VolumeInfo volume_info );