예제 #1
0
 protected virtual void CreateInstance()
 {
     if (m_currentContainer && m_currentContainer.handle && m_currentAsset && m_currentAsset.handle)
     {
         int        group = m_particleGroup < 0 ? ++sm_nextGroup : m_particleGroup;
         Flex.Phase flags = Flex.Phase.Default;
         if (m_selfCollide)
         {
             flags |= Flex.Phase.SelfCollide;
         }
         if (m_selfCollideFilter)
         {
             flags |= Flex.Phase.SelfCollideFilter;
         }
         if (m_fluid)
         {
             flags |= Flex.Phase.Fluid;
         }
         m_phase          = Flex.MakePhase(group, flags);
         m_instanceHandle = m_currentContainer.CreateInstance(m_currentAsset.handle, transform.localToWorldMatrix, Vector3.zero, m_phase, m_massScale);
         if (m_instanceHandle)
         {
             FlexExt.Instance instance = m_instanceHandle.instance;
             m_indices    = new int[m_currentAsset.maxParticles];
             m_indexCount = instance.numParticles;
             if (m_indexCount > 0)
             {
                 FlexUtils.FastCopy(instance.particleIndices, 0, ref m_indices[0], 0, sizeof(int) * m_indexCount);
             }
         }
     }
 }
예제 #2
0
        private void ProcessParticles(bool countChanged)
        {
            for (int iId = 0; iId < m_flexGameObjects.Count && iId < m_activeInstacesCount; iId++)
            {
                Transform tr = m_flexGameObjects[iId].transform;

                FlexParticles particles = m_flexGameObjects[iId];
                if (particles && particles.enabled)
                {
                    if (m_flexGameObjects[iId].m_initialized) //if initialized just update some arrays
                    {
                        Array.Copy(particles.m_particles, 0, m_particles, particles.m_particlesIndex, particles.m_particlesCount);
                        Array.Copy(particles.m_restParticles, 0, m_restParticles, particles.m_particlesIndex, particles.m_particlesCount);
                        Array.Copy(particles.m_velocities, 0, m_velocities, particles.m_particlesIndex, particles.m_particlesCount);
                        Array.Copy(particles.m_particlesActivity, 0, m_particlesActivity, particles.m_particlesIndex, particles.m_particlesCount);

                        particles.m_collisionGroup = particles.m_collisionGroup == -1 ? iId : particles.m_collisionGroup;
                        int phase = Flex.MakePhase(particles.m_collisionGroup, (int)particles.m_interactionType);

                        for (int pId = 0; pId < particles.m_particlesCount; pId++)
                        {
                            m_phases[pId + particles.m_particlesIndex] = phase;
                        }
                        //needs to update this if the flex game object is changing position in the containcer (i.e. iId)
                        //particles.m_collisionGroup = particles.m_collisionGroup == -1 ? iId : particles.m_collisionGroup;
                        //int phase = Flex.MakePhase(particles.m_collisionGroup, (int)particles.m_interactionType);
                        //for (int pId = 0; pId < particles.m_particlesCount; pId++)
                        //{
                        //    m_phases[pId + particles.m_particlesIndex] = phase;
                        //}
                    }
                    else // do the full init
                    {
                        //if group is -1 set the consecutive bodyId, else use a user defined number
                        particles.m_collisionGroup = particles.m_collisionGroup == -1 ? iId : particles.m_collisionGroup;
                        int   phase   = Flex.MakePhase(particles.m_collisionGroup, (int)particles.m_interactionType);
                        float invMass = particles.m_mass == 0 ? 0.0f : 1.0f / particles.m_mass;
                        for (int pId = 0; pId < particles.m_particlesCount; pId++)
                        {
                            m_particles[pId + particles.m_particlesIndex].pos     = tr.TransformPoint(particles.m_particles[pId].pos);
                            m_particles[pId + particles.m_particlesIndex].invMass = particles.m_overrideMass ? invMass : particles.m_particles[pId].invMass;
                            m_restParticles[pId + particles.m_particlesIndex]     = particles.m_restParticles[pId];

                            //m_velocities[pId + particles.m_particlesIndex] = particles.m_velocities[pId];
                            m_velocities[pId + particles.m_particlesIndex]        = particles.m_initialVelocity;
                            m_colors[pId + particles.m_particlesIndex]            = particles.m_colours[pId];
                            m_phases[pId + particles.m_particlesIndex]            = phase;
                            m_particlesActivity[pId + particles.m_particlesIndex] = particles.m_particlesActivity[pId];
                        }

                        m_flexGameObjects[iId].m_initialized = true;
                    }
                }
            }

            //m_particlesCount = UpdateActiveSet();

            m_activeParticlesCount = UpdateActiveSet();
        }
예제 #3
0
    public void TestSetParticlesPhases()
    {
        float DELTA_T = 0.016f;
        float INTERACTION_DISTANCE = 0.5f;
        float SOLID_REST_DISTANCE  = 0.2f;

        Flex.Library    lib  = Flex.Init(Flex.FLEX_VERSION, ErrorCallback);
        Flex.SolverDesc desc = default(Flex.SolverDesc);
        Flex.SetSolverDescDefaults(ref desc);
        desc.maxParticles        = 1000;
        desc.maxDiffuseParticles = 1000;
        Flex.Solver solver = Flex.CreateSolver(lib, ref desc);

        Flex.Params prms = new Flex.Params();
        Flex.GetParams(solver, ref prms);
        prms.radius            = INTERACTION_DISTANCE;
        prms.solidRestDistance = SOLID_REST_DISTANCE;
        Flex.SetParams(solver, ref prms);

        Flex.Buffer particles = CreateBuffer(lib, 2, 4, new float[]
        {
            -0.001f, 0.0f, 0.0f, 1.0f,
            0.001f, 0.0f, 0.0f, 1.0f,
        });
        Flex.SetParticles(solver, particles);

        Flex.Buffer phases = CreateBuffer(lib, 2, 1, new int[]
        {
            Flex.MakePhase(1, Flex.Phase.SelfCollide),
            Flex.MakePhase(1, Flex.Phase.SelfCollide),
        });
        Flex.SetPhases(solver, phases);

        Flex.SetActiveCount(solver, 2);

        Flex.Buffer active = CreateBuffer(lib, 2, 1, new int[]
        {
            0, 1,
        });
        Flex.SetActive(solver, active);

        Flex.UpdateSolver(solver, DELTA_T, 1);

        Flex.GetParticles(solver, particles);
        float[] values; ReadBuffer(lib, particles, 2, 4, out values);

        Assert.AreEqual(SOLID_REST_DISTANCE, Vector3.Distance(new Vector3(values[0], values[1], values[2]), new Vector3(values[4], values[5], values[6])));

        Flex.FreeBuffer(particles);
        Flex.FreeBuffer(phases);
        Flex.FreeBuffer(active);

        Flex.DestroySolver(solver);
        Flex.Shutdown(lib);
    }
예제 #4
0
    void spawnParticles(IntPtr particles, IntPtr velocities, IntPtr phases)
    {
        Vector4 particle;
        Vector3 velocity;
        int     phase = Flex.MakePhase(0, Flex.Phase.SelfCollide | Flex.Phase.Fluid);

        unsafe
        {
            Vector4 *particlesPtr  = (Vector4 *)particles;
            Vector3 *velocitiesPtr = (Vector3 *)velocities;
            int *    phasesPtr     = (int *)phases;

            for (int i = 0; i < 28; ++i)
            {
                particlesPtr[i]  = new Vector4(UnityEngine.Random.Range(-10.0f, 10.0f), -3.5f, 13.0f, 1.0f);
                velocitiesPtr[i] = new Vector3(0.0f, 0.0f, 0.0f);
                phasesPtr[i]     = phase;
            }
        }
    }
예제 #5
0
    public void TestCreateDestroyInstance()
    {
        Flex.Library    lib    = Flex.Init(Flex.FLEX_VERSION, ErrorCallback);
        Flex.SolverDesc slvDsc = default(Flex.SolverDesc);
        Flex.SetSolverDescDefaults(ref slvDsc);
        slvDsc.maxParticles = 1000;
        Flex.Solver       solver    = Flex.CreateSolver(lib, ref slvDsc);
        FlexExt.Container container = FlexExt.CreateContainer(lib, solver, 1000);

        FlexExt.Asset.Handle asset = CreateTestClothAsset();

        FlexExt.ParticleData data = FlexExt.MapParticleData(container);

        Matrix4x4 transform = Matrix4x4.identity;

        FlexExt.Instance.Handle instance = FlexExt.CreateInstance(container, ref data, asset, ref transform, 1.0f, 1.0f, 1.0f, Flex.MakePhase(1, Flex.Phase.Default), 1.0f);

        Assert.AreEqual(asset.asset.numParticles, instance.instance.numParticles);

        FlexExt.DestroyInstance(container, instance);

        FlexExt.UnmapParticleData(container);

        FlexExt.DestroyAsset(asset);

        FlexExt.DestroyContainer(container);
        Flex.DestroySolver(solver);
        Flex.Shutdown(lib);
    }
예제 #6
0
        void OnGUI()
        {
            bool hasFlexComponent = false;

            GUILayout.Label("uFlex v0.5 - Developer Utils", EditorStyles.whiteLargeLabel);

            EditorGUILayout.HelpBox("This window is for advanced users. Improper use may break the uFlex objects.", MessageType.Warning);

            if (Selection.activeGameObject)
            {
                GUILayout.Label(Selection.activeGameObject.name, EditorStyles.boldLabel);

                FlexParticles particles = Selection.activeGameObject.GetComponent <FlexParticles>();
                if (particles)
                {
                    EditorGUILayout.Separator();
                    GUILayout.Label("Particles", EditorStyles.boldLabel);
                    EditorGUILayout.BeginHorizontal();
                    m_mass = EditorGUILayout.FloatField("Particles Masses: ", m_mass);
                    if (GUILayout.Button("Set "))
                    {
                        Debug.Log("Mass Set To " + m_mass);
                        float invMass = 1.0f / m_mass;
                        for (int i = 0; i < particles.m_particlesCount; i++)
                        {
                            //skip locked particles
                            if (particles.m_particles[i].invMass == 0)
                            {
                                continue;
                            }

                            particles.m_particles[i].invMass = invMass;
                        }
                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    if (GUILayout.Button("Apply Color"))
                    {
                        for (int i = 0; i < particles.m_particlesCount; i++)
                        {
                            particles.m_colours[i] = particles.m_colour;
                        }
                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    if (GUILayout.Button("Randomize Colors"))
                    {
                        for (int i = 0; i < particles.m_particlesCount; i++)
                        {
                            //  particles.m_colours[i] = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value, 1.0f);
                            particles.m_colours[i] = UnityEngine.Random.ColorHSV(0.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f);
                        }
                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    EditorGUILayout.EndHorizontal();

                    if (GUILayout.Button("Randomize Spacing"))
                    {
                        for (int i = 0; i < particles.m_particlesCount; i++)
                        {
                            particles.m_particles[i].pos += new Vector3(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value) * 0.1f;
                        }
                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    if (GUILayout.Button("Activate All"))
                    {
                        particles.m_particlesActivity = new bool[particles.m_particlesCount];
                        for (int i = 0; i < particles.m_particlesCount; i++)
                        {
                            particles.m_particlesActivity[i] = true;
                        }
                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    if (GUILayout.Button("Deactivate All"))
                    {
                        particles.m_particlesActivity = new bool[particles.m_particlesCount];
                        for (int i = 0; i < particles.m_particlesCount; i++)
                        {
                            particles.m_particlesActivity[i] = false;
                        }
                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    //if (GUILayout.Button("Deactivate Half"))
                    //{
                    //    particles.m_particlesActivity = new bool[particles.m_particlesCount];
                    //    for (int i = 0; i < particles.m_particlesCount / 2; i++)
                    //    {
                    //        particles.m_particlesActivity[i] = true;
                    //    }

                    //    for (int i = particles.m_particlesCount / 2; i < particles.m_particlesCount; i++)
                    //    {
                    //        particles.m_particlesActivity[i] = false;
                    //    }
                    //    SceneView.RepaintAll();
                    //    EditorUtility.SetDirty(particles);

                    //}

                    if (GUILayout.Button("Upgrade to v0.5"))
                    {
                        particles.m_densities         = new float[particles.m_maxParticlesCount];
                        particles.m_velocities        = new Vector3[particles.m_maxParticlesCount];
                        particles.m_phases            = new int[particles.m_maxParticlesCount];
                        particles.m_restParticles     = new Particle[particles.m_maxParticlesCount];
                        particles.m_smoothedParticles = new Particle[particles.m_maxParticlesCount];
                        particles.m_particlesActivity = new bool[particles.m_maxParticlesCount];

                        int phase = Flex.MakePhase(particles.m_collisionGroup, (int)particles.m_interactionType);

                        for (int i = 0; i < particles.m_particlesCount; i++)
                        {
                            particles.m_velocities[i]        = particles.m_initialVelocity;
                            particles.m_particlesActivity[i] = true;
                            particles.m_phases[i]            = phase;

                            particles.m_restParticles[i]     = particles.m_particles[i];
                            particles.m_smoothedParticles[i] = particles.m_particles[i];
                        }

                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    if (GUILayout.Button("Add FlexRopeMesh"))
                    {
                        FlexRopeMesh frm = Selection.activeGameObject.AddComponent <FlexRopeMesh>();

                        frm.m_particles = particles;
                        frm.InitRope(particles.m_particlesCount);

                        MeshFilter meshFilter = Selection.activeGameObject.AddComponent <MeshFilter>();
                        meshFilter.sharedMesh = frm.m_mesh;

                        MeshRenderer rend = Selection.activeGameObject.AddComponent <MeshRenderer>();
                        Material     mat  = new Material(Shader.Find("Diffuse"));
                        mat.name      = "RopeMat";
                        mat.color     = Color.yellow;
                        rend.material = mat;

                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    hasFlexComponent = true;
                }


                FlexSprings springs = Selection.activeGameObject.GetComponent <FlexSprings>();
                if (springs)
                {
                    EditorGUILayout.Separator();
                    GUILayout.Label("Springs", EditorStyles.boldLabel);

                    EditorGUILayout.BeginHorizontal();
                    if (GUILayout.Button("Add Long Range Attachments to Rope"))
                    {
                        int   ropeSegments = particles.m_particlesCount - 1;
                        float restLength   = Vector3.Distance(particles.m_particles[0].pos, particles.m_particles[1].pos);
                        //distance + bend + tether (long range attachments)
                        int springsCount = ropeSegments + (ropeSegments - 1) + ropeSegments;

                        springs.m_springsCount = springsCount;

                        Array.Resize <int>(ref springs.m_springIndices, springsCount * 2);
                        Array.Resize <float>(ref springs.m_springCoefficients, springsCount);
                        Array.Resize <float>(ref springs.m_springRestLengths, springsCount);

                        for (int i = 0; i < ropeSegments; i++)
                        {
                            springs.m_springIndices[(ropeSegments + ropeSegments - 1) * 2 + i * 2 + 0] = 0;
                            springs.m_springIndices[(ropeSegments + ropeSegments - 1) * 2 + i * 2 + 1] = i + 1;

                            //negative stiffness means tether constraints
                            //(i.e. prevents spring stretch but not its compression)
                            springs.m_springCoefficients[(ropeSegments + ropeSegments - 1) + i] = -0.001f;
                            springs.m_springRestLengths[(ropeSegments + ropeSegments - 1) + i]  = i * restLength;
                        }
                    }
                    EditorGUILayout.EndHorizontal();
                }



                FlexShapeMatching shapes = Selection.activeGameObject.GetComponent <FlexShapeMatching>();
                if (shapes)
                {
                    EditorGUILayout.Separator();
                    GUILayout.Label("Shapes", EditorStyles.boldLabel);

                    EditorGUILayout.BeginHorizontal();
                    m_clusterStiffness = EditorGUILayout.FloatField("Clusters Stiffness: ", m_clusterStiffness);
                    if (GUILayout.Button("Set"))
                    {
                        for (int i = 0; i < shapes.m_shapesCount; i++)
                        {
                            shapes.m_shapeCoefficients[i] = m_clusterStiffness;
                        }
                        Debug.Log("Clusters Ks Set To " + m_clusterStiffness);
                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    EditorGUILayout.EndHorizontal();


                    EditorGUILayout.Separator();
                    GUILayout.Label("Skinning");
                    EditorGUILayout.BeginHorizontal();
                    m_skinFalloff = EditorGUILayout.FloatField("Falloff: ", m_skinFalloff);
                    m_skinMaxDist = EditorGUILayout.FloatField("Max Distance: ", m_skinMaxDist);
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    inputMesh = EditorGUILayout.ObjectField(new GUIContent("Input Mesh", "The input mesh"), inputMesh, typeof(Mesh), true) as Mesh;

                    if (GUILayout.Button("Generate Skinning") && inputMesh)
                    {
                        Vector3[] vertices = inputMesh.vertices;

                        float[] skinWeights = new float[inputMesh.vertexCount * 4];
                        int[]   skinIndices = new int[inputMesh.vertexCount * 4];
                        FlexExt.flexExtCreateSoftMeshSkinning(vertices, inputMesh.vertexCount, shapes.m_shapeCenters, shapes.m_shapesCount, m_skinFalloff, m_skinMaxDist, skinWeights, skinIndices);

                        Mesh mesh = new Mesh();
                        mesh.name      = this.inputMesh.name + "FlexMesh";
                        mesh.vertices  = this.inputMesh.vertices;
                        mesh.triangles = this.inputMesh.triangles;
                        mesh.normals   = this.inputMesh.normals;
                        mesh.uv        = this.inputMesh.uv;

                        Transform[]  bones       = new Transform[shapes.m_shapesCount];
                        BoneWeight[] boneWeights = new BoneWeight[this.inputMesh.vertexCount];
                        Matrix4x4[]  bindPoses   = new Matrix4x4[shapes.m_shapesCount];

                        Vector3[] rigidRestPoses = new Vector3[shapes.m_shapesCount];

                        for (int i = 0; i < shapes.m_shapesCount; i++)
                        {
                            rigidRestPoses[i] = shapes.m_shapeCenters[i];

                            bones[i]               = new GameObject("FlexShape_" + i).transform;
                            bones[i].parent        = Selection.activeGameObject.transform;
                            bones[i].localPosition = shapes.m_shapeCenters[i];
                            bones[i].localRotation = Quaternion.identity;

                            bindPoses[i] = bones[i].worldToLocalMatrix * Selection.activeGameObject.transform.localToWorldMatrix;
                        }

                        for (int i = 0; i < this.inputMesh.vertexCount; i++)
                        {
                            boneWeights[i].boneIndex0 = skinIndices[i * 4 + 0];
                            boneWeights[i].boneIndex1 = skinIndices[i * 4 + 1];
                            boneWeights[i].boneIndex2 = skinIndices[i * 4 + 2];
                            boneWeights[i].boneIndex3 = skinIndices[i * 4 + 3];

                            boneWeights[i].weight0 = skinWeights[i * 4 + 0];
                            boneWeights[i].weight1 = skinWeights[i * 4 + 1];
                            boneWeights[i].weight2 = skinWeights[i * 4 + 2];
                            boneWeights[i].weight3 = skinWeights[i * 4 + 3];
                        }

                        mesh.bindposes   = bindPoses;
                        mesh.boneWeights = boneWeights;

                        mesh.RecalculateNormals();
                        mesh.RecalculateBounds();

                        AssetDatabase.CreateAsset(mesh, "Assets/uFlex/Meshes/" + this.inputMesh.name + "FlexMesh.asset");
                        AssetDatabase.SaveAssets();

                        FlexSkinnedMesh skin = Selection.activeGameObject.AddComponent <FlexSkinnedMesh>();
                        skin.m_bones       = bones;
                        skin.m_boneWeights = boneWeights;
                        skin.m_bindPoses   = bindPoses;

                        SkinnedMeshRenderer rend = Selection.activeGameObject.AddComponent <SkinnedMeshRenderer>();
                        rend.sharedMesh = mesh;
                        //  rend.sharedMesh = this.inputMesh;
                        rend.updateWhenOffscreen = true;
                        rend.quality             = SkinQuality.Bone4;
                        rend.bones = bones;


                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }
                    EditorGUILayout.EndHorizontal();


                    if (GUILayout.Button("Upgrade to v0.5"))
                    {
                        int shapeIndex       = 0;
                        int shapeIndexOffset = 0;

                        shapes.m_shapeTranslations  = new Vector3[shapes.m_shapesCount];
                        shapes.m_shapeRotations     = new Quaternion[shapes.m_shapesCount];
                        shapes.m_shapeRestPositions = new Vector3[shapes.m_shapeIndicesCount];

                        int shapeStart = 0;
                        for (int s = 0; s < shapes.m_shapesCount; s++)
                        {
                            shapes.m_shapeTranslations[s] = new Vector3();
                            shapes.m_shapeRotations[s]    = Quaternion.identity;

                            //    int indexOffset = shapeIndexOffset;

                            //m_shapeOffsets[shapeIndex + 1] = shapes.m_shapeOffsets[s] + indexOffset;
                            //m_shapeCoefficients[shapeIndex] = shapes.m_shapeCoefficients[s];
                            //m_shapeTranslations[shapeIndex] = shapes.m_shapeTranslations[s];
                            //m_shapeRotations[shapeIndex] = shapes.m_shapeRotations[s];

                            shapeIndex++;

                            int shapeEnd = shapes.m_shapeOffsets[s];

                            for (int i = shapeStart; i < shapeEnd; ++i)
                            {
                                int p = shapes.m_shapeIndices[i];

                                // remap indices and create local space positions for each shape
                                Vector3 pos = particles.m_particles[p].pos;
                                shapes.m_shapeRestPositions[shapeIndexOffset] = pos - shapes.m_shapeCenters[s];

                                //   m_shapeIndices[shapeIndexOffset] = shapes.m_shapeIndices[i] + particles.m_particlesIndex;

                                shapeIndexOffset++;
                            }

                            shapeStart = shapeEnd;
                        }



                        SceneView.RepaintAll();
                        EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
                    }

                    hasFlexComponent = true;
                }
            }

            if (!hasFlexComponent)
            {
                GUILayout.Label("Select GameObject with Flex Components", EditorStyles.boldLabel);
            }
        }