예제 #1
0
        public override void GenerateDistribution()
        {
            distribution.Clear();

            if (particleSize <= 0 || mesh == null)
            {
                return;
            }

            // Calculate voxel size so that no more than 32^3 points are created:
            Vector3 boundsSize = Vector3.Scale(mesh.bounds.size, Vector3.one);
            float   voxelSize  = Mathf.Max(boundsSize.x / 32.0f, boundsSize.y / 32.0f, boundsSize.z / 32.0f, particleSize);

            // Voxelize mesh:
            MeshVoxelizer voxelizer = new MeshVoxelizer(mesh, voxelSize);

            voxelizer.Voxelize(Vector3.one);

            MeshVoxelizer.Voxel[,,] voxels = voxelizer.voxels;

            // Create one distribution point at the center of each volume/surface voxel:
            for (int x = 0; x < voxels.GetLength(0); ++x)
            {
                for (int y = 0; y < voxels.GetLength(1); ++y)
                {
                    for (int z = 0; z < voxels.GetLength(2); ++z)
                    {
                        if (voxels[x, y, z] != MeshVoxelizer.Voxel.Outside)
                        {
                            Vector3 pos = new Vector3(voxelizer.Origin.x + x + 0.5f, voxelizer.Origin.y + y + 0.5f, voxelizer.Origin.z + z + 0.5f) * voxelSize;
                            distribution.Add(new ObiEmitterShape.DistributionPoint(pos, Vector3.forward));
                        }
                    }
                }
            }
        }
예제 #2
0
        protected override IEnumerator Initialize()
        {
            if (inputMesh == null || !inputMesh.isReadable)
            {
                // TODO: return an error in the coroutine.
                Debug.LogError("The input mesh is null, or not readable.");
                yield break;
            }

            ClearParticleGroups();

            List <Vector3> particles = new List <Vector3>();
            List <Vector3> normals   = new List <Vector3>();

            // Calculate voxel size so that no more than 32^3 particles are created:
            Vector3 boundsSize = Vector3.Scale(inputMesh.bounds.size, Vector3.one);
            float   voxelSize  = Mathf.Max(boundsSize.x / 32.0f, boundsSize.y / 32.0f, boundsSize.z / 32.0f, particleRadius * 2 * (1 - particleOverlap));

            // Voxelize mesh and calculate discrete distance field:
            MeshVoxelizer      voxelizer = new MeshVoxelizer(inputMesh, voxelSize);
            VoxelDistanceField df        = new VoxelDistanceField(voxelizer);

            voxelizer.Voxelize(scale);
            df.JumpFlood();

            MeshVoxelizer.Voxel[,,] voxels = voxelizer.voxels;

            for (int x = 0; x < voxels.GetLength(0); ++x)
            {
                for (int y = 0; y < voxels.GetLength(1); ++y)
                {
                    for (int z = 0; z < voxels.GetLength(2); ++z)
                    {
                        if (voxels[x, y, z] != MeshVoxelizer.Voxel.Outside)
                        {
                            particles.Add(new Vector3(voxelizer.Origin.x + x + 0.5f, voxelizer.Origin.y + y + 0.5f, voxelizer.Origin.z + z + 0.5f) * voxelSize);
                            normals.Add(df.distanceField[x, y, z] - new Vector3Int(x, y, z));
                        }
                    }
                }
            }

            positions           = new Vector3[particles.Count];
            orientations        = new Quaternion[particles.Count];
            restPositions       = new Vector4[particles.Count];
            restOrientations    = new Quaternion[particles.Count];
            velocities          = new Vector3[particles.Count];
            angularVelocities   = new Vector3[particles.Count];
            invMasses           = new float[particles.Count];
            invRotationalMasses = new float[particles.Count];
            principalRadii      = new Vector3[particles.Count];
            phases = new int[particles.Count];
            colors = new Color[particles.Count];

            m_ActiveParticleCount = particles.Count;

            for (int i = 0; i < particles.Count; ++i)
            {
                // Perform ellipsoid fitting:
                Vector3        avgNormal         = Vector3.zero;
                List <Vector3> neighbourVertices = new List <Vector3>();

                Vector3    centroid        = particles[i];
                Quaternion orientation     = Quaternion.LookRotation(normals[i]);
                Vector3    principalValues = Vector3.one * voxelSize * (0.5f + particleOverlap);

                invRotationalMasses[i] = invMasses[i] = 1.0f;
                positions[i]           = Vector3.Lerp(particles[i], centroid, shapeSmoothing);
                restPositions[i]       = positions[i];
                orientations[i]        = orientation;
                restOrientations[i]    = orientation;
                restPositions[i][3]    = 1;           // activate rest position.
                principalRadii[i]      = principalValues;
                phases[i] = ObiUtils.MakePhase(1, 0); //Oni.MakePhase(1, (selfCollisions ? Oni.ParticlePhase.SelfCollide : 0) | (oneSided ? Oni.ParticlePhase.OneSided : 0));
                colors[i] = Color.white;

                if (i % 100 == 0)
                {
                    yield return(new CoroutineJob.ProgressInfo("ObiSoftbody: generating particles...", i / (float)particles.Count));
                }
            }

            IEnumerator sc = CreateShapeMatchingConstraints(particles);

            while (sc.MoveNext())
            {
                yield return(sc.Current);
            }

            // Initialize pin constraints:
            pinConstraintsData = new ObiPinConstraintsData();
            ObiPinConstraintsBatch pinBatch = new ObiPinConstraintsBatch();

            pinConstraintsData.AddBatch(pinBatch);
        }
 public VoxelDistanceField(MeshVoxelizer voxelizer)
 {
     this.voxelizer = voxelizer;
 }