08-11-2022, 06:21 AM
(24-06-2022, 07:36 AM)josemendez Wrote: Btw, there's a known bug in vertex surface sampling. Replace the Initialize() method in Obi/Scripts/Softbody/Blueprints/ObiSoftbodySurfaceBlueprint.cs with this:
Code:protected override IEnumerator Initialize()
{
if (inputMesh == null || !inputMesh.isReadable)
{
Debug.LogError("The input mesh is null, or not readable.");
yield break;
}
ClearParticleGroups();
// Prepare candidate particle arrays:
List<Vector3> particlePositions = new List<Vector3>();
List<Vector3> particleNormals = new List<Vector3>();
// Prepare constraint arrays:
particleIndices = new List<int>();
constraintIndices = new List<int>();
// Transform mesh data:
blueprintTransform = Matrix4x4.TRS(Vector3.zero, rotation, scale);
Vector3[] vertices = inputMesh.vertices;
Vector3[] normals = inputMesh.normals;
int[] tris = inputMesh.triangles;
Bounds transformedBounds = new Bounds();
for (int i = 0; i < vertices.Length; ++i)
{
vertices[i] = blueprintTransform.MultiplyPoint3x4(vertices[i]);
transformedBounds.Encapsulate(vertices[i]);
}
for (int i = 0; i < normals.Length; ++i)
normals[i] = Vector3.Normalize(blueprintTransform.MultiplyVector(normals[i]));
// initialize arrays:
particleType = new List<ParticleType>();
//voxelize for cluster placement:
var voxelize = VoxelizeForShapeAnalysis(transformedBounds.size);
while (voxelize.MoveNext()) yield return voxelize.Current;
//voxelize for surface:
voxelize = VoxelizeForSurfaceSampling(transformedBounds.size);
while (voxelize.MoveNext()) yield return voxelize.Current;
if (surfaceSamplingMode == SurfaceSamplingMode.Voxels)
{
var surface = VoxelSampling(surfaceVoxelizer, particlePositions, particleNormals, MeshVoxelizer.Voxel.Boundary, ParticleType.Surface);
while (surface.MoveNext()) yield return surface.Current;
IEnumerator ip = InsertParticlesIntoVoxels(surfaceVoxelizer, particlePositions);
while (ip.MoveNext()) yield return ip.Current;
IEnumerator vc = CreateClustersFromVoxels(surfaceVoxelizer, particlePositions, VoxelConnectivity.Faces | VoxelConnectivity.Edges, new List<ParticleType>(){ParticleType.Surface});
while (vc.MoveNext()) yield return vc.Current;
for (int i = 0; i < particlePositions.Count; ++i)
particlePositions[i] = ProjectOnMesh(particlePositions[i], vertices, tris);
}
else if (surfaceSamplingMode == SurfaceSamplingMode.Vertices)
{
var sv = VertexSampling(vertices, particlePositions);
while (sv.MoveNext()) yield return sv.Current;
// map vertices to particles:
var mp = MapVerticesToParticles(vertices, particlePositions);
while (mp.MoveNext()) yield return mp.Current;
var ss = SurfaceMeshShapeMatchingConstraints(particlePositions,tris);
while (ss.MoveNext()) yield return ss.Current;
}
if (volumeSamplingMode == VolumeSamplingMode.Voxels)
{
// sample the volume of the mesh:
voxelize = VoxelizeForVolumeSampling(transformedBounds.size);
while (voxelize.MoveNext()) yield return voxelize.Current;
var volume = VoxelSampling(volumeVoxelizer, particlePositions, particleNormals, MeshVoxelizer.Voxel.Inside, ParticleType.Volume);
while (volume.MoveNext()) yield return volume.Current;
var ip = InsertParticlesIntoVoxels(volumeVoxelizer, particlePositions);
while (ip.MoveNext()) yield return ip.Current;
var vc = CreateClustersFromVoxels(volumeVoxelizer, particlePositions, VoxelConnectivity.Faces, new List<ParticleType>() { ParticleType.Volume });
while (vc.MoveNext()) yield return vc.Current;
vc = CreateClustersFromVoxels(volumeVoxelizer, particlePositions, VoxelConnectivity.All, new List<ParticleType>() { ParticleType.Volume | ParticleType.Surface });
while (vc.MoveNext()) yield return vc.Current;
// map vertices to particles:
var mp = MapVerticesToParticles(vertices, particlePositions);
while (mp.MoveNext()) yield return mp.Current;
}
// sample skeleton:
var sk = SkeletonSampling(transformedBounds.size, particlePositions, particleNormals);
while (sk.MoveNext()) yield return sk.Current;
// create skeleton clusters:
if (skeleton != null)
{
var sc = CreateClustersFromSkeleton(particlePositions);
while (sc.MoveNext()) yield return sc.Current;
}
// generate particles:
var generate = GenerateParticles(normals, particlePositions, particleNormals);
while (generate.MoveNext()) yield return generate.Current;
// generate shape matching constraints:
IEnumerator bc = CreateShapeMatchingConstraints(particlePositions);
while (bc.MoveNext()) yield return bc.Current;
generatedMesh = inputMesh;
}
Would you be able to sticky this code somewhere / put it somewhere more easily found?