|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "../include/NvFlexExt.h" |
|
|
|
|
|
#include "../core/maths.h" |
|
|
#include "../core/voxelize.h" |
|
|
#include "../core/sdf.h" |
|
|
|
|
|
#include <vector> |
|
|
|
|
|
namespace |
|
|
{ |
|
|
|
|
|
float SampleSDF(const float* sdf, int dim, int x, int y, int z) |
|
|
{ |
|
|
assert(x < dim && x >= 0); |
|
|
assert(y < dim && y >= 0); |
|
|
assert(z < dim && z >= 0); |
|
|
|
|
|
return sdf[z*dim*dim + y*dim + x]; |
|
|
} |
|
|
|
|
|
|
|
|
Vec3 SampleSDFGrad(const float* sdf, int dim, int x, int y, int z) |
|
|
{ |
|
|
int x0 = std::max(x-1, 0); |
|
|
int x1 = std::min(x+1, dim-1); |
|
|
|
|
|
int y0 = std::max(y-1, 0); |
|
|
int y1 = std::min(y+1, dim-1); |
|
|
|
|
|
int z0 = std::max(z-1, 0); |
|
|
int z1 = std::min(z+1, dim-1); |
|
|
|
|
|
float dx = (SampleSDF(sdf, dim, x1, y, z) - SampleSDF(sdf, dim, x0, y, z))*(dim*0.5f); |
|
|
float dy = (SampleSDF(sdf, dim, x, y1, z) - SampleSDF(sdf, dim, x, y0, z))*(dim*0.5f); |
|
|
float dz = (SampleSDF(sdf, dim, x, y, z1) - SampleSDF(sdf, dim, x, y, z0))*(dim*0.5f); |
|
|
|
|
|
return Vec3(dx, dy, dz); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
NvFlexExtAsset* NvFlexExtCreateRigidFromMesh(const float* vertices, int numVertices, const int* indices, int numTriangleIndices, float spacing, float expand) |
|
|
{ |
|
|
|
|
|
|
|
|
Vec3 meshOffset(0.0f); |
|
|
for (int i = 0; i < numVertices; i++) |
|
|
{ |
|
|
meshOffset += ((Vec3*)vertices)[i]; |
|
|
} |
|
|
meshOffset /= float(numVertices); |
|
|
|
|
|
Vec3* relativeVertices = new Vec3[numVertices]; |
|
|
for (int i = 0; i < numVertices; i++) |
|
|
{ |
|
|
relativeVertices[i] += ((Vec3*)vertices)[i] - meshOffset; |
|
|
} |
|
|
|
|
|
std::vector<Vec4> particles; |
|
|
std::vector<Vec4> normals; |
|
|
std::vector<int> phases; |
|
|
|
|
|
const Vec3* positions = relativeVertices; |
|
|
|
|
|
Vec3 meshLower(FLT_MAX), meshUpper(-FLT_MAX); |
|
|
for (int i=0; i < numVertices; ++i) |
|
|
{ |
|
|
meshLower = Min(meshLower, positions[i]); |
|
|
meshUpper = Max(meshUpper, positions[i]); |
|
|
} |
|
|
|
|
|
Vec3 edges = meshUpper-meshLower; |
|
|
float maxEdge = std::max(std::max(edges.x, edges.y), edges.z); |
|
|
|
|
|
|
|
|
|
|
|
float spacingEps = spacing*(1.0f - 1e-4f); |
|
|
|
|
|
|
|
|
int dx, dy, dz; |
|
|
dx = spacing > edges.x ? 1 : int(edges.x/spacingEps); |
|
|
dy = spacing > edges.y ? 1 : int(edges.y/spacingEps); |
|
|
dz = spacing > edges.z ? 1 : int(edges.z/spacingEps); |
|
|
|
|
|
int maxDim = std::max(std::max(dx, dy), dz); |
|
|
|
|
|
|
|
|
meshLower -= 2.0f*Vec3(spacing); |
|
|
meshUpper += 2.0f*Vec3(spacing); |
|
|
maxDim += 4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Vec3 meshShift; |
|
|
meshShift.x = 0.5f * (spacing - (edges.x - (dx-1)*spacing)); |
|
|
meshShift.y = 0.5f * (spacing - (edges.y - (dy-1)*spacing)); |
|
|
meshShift.z = 0.5f * (spacing - (edges.z - (dz-1)*spacing)); |
|
|
meshLower -= meshShift; |
|
|
|
|
|
|
|
|
if (maxDim > 64) |
|
|
return NULL; |
|
|
|
|
|
std::vector<uint32_t> voxels(maxDim*maxDim*maxDim); |
|
|
|
|
|
Voxelize(relativeVertices, numVertices, indices, numTriangleIndices, maxDim, maxDim, maxDim, &voxels[0], meshLower, meshLower + Vec3(maxDim*spacing)); |
|
|
|
|
|
delete[] relativeVertices; |
|
|
|
|
|
std::vector<float> sdf(maxDim*maxDim*maxDim); |
|
|
MakeSDF(&voxels[0], maxDim, maxDim, maxDim, &sdf[0]); |
|
|
|
|
|
Vec3 center; |
|
|
|
|
|
for (int x=0; x < maxDim; ++x) |
|
|
{ |
|
|
for (int y=0; y < maxDim; ++y) |
|
|
{ |
|
|
for (int z=0; z < maxDim; ++z) |
|
|
{ |
|
|
const int index = z*maxDim*maxDim + y*maxDim + x; |
|
|
|
|
|
|
|
|
if (voxels[index]) |
|
|
{ |
|
|
Vec3 position = meshLower + spacing*Vec3(float(x) + 0.5f, float(y) + 0.5f, float(z) + 0.5f); |
|
|
|
|
|
|
|
|
Vec3 n = SafeNormalize(SampleSDFGrad(&sdf[0], maxDim, x, y, z)); |
|
|
float d = sdf[index]*maxEdge; |
|
|
|
|
|
|
|
|
position += n*expand; |
|
|
|
|
|
normals.push_back(Vec4(n, d)); |
|
|
particles.push_back(Vec4(position.x, position.y, position.z, 1.0f)); |
|
|
phases.push_back(0); |
|
|
|
|
|
center += position; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
const int numParticles = int(particles.size()); |
|
|
|
|
|
|
|
|
center /= float(numParticles); |
|
|
center += meshOffset; |
|
|
|
|
|
for (int i = 0; i < numParticles; i++) { |
|
|
particles[i] += Vec4(meshOffset, 0.0f); |
|
|
} |
|
|
|
|
|
NvFlexExtAsset* asset = new NvFlexExtAsset(); |
|
|
memset(asset, 0, sizeof(*asset)); |
|
|
|
|
|
if (numParticles) |
|
|
{ |
|
|
asset->numParticles = numParticles; |
|
|
asset->maxParticles = numParticles; |
|
|
|
|
|
asset->particles = new float[numParticles*4]; |
|
|
memcpy(asset->particles, &particles[0], sizeof(Vec4)*numParticles); |
|
|
|
|
|
asset->numShapes = 1; |
|
|
asset->numShapeIndices = numParticles; |
|
|
|
|
|
|
|
|
asset->shapeIndices = new int[numParticles]; |
|
|
|
|
|
for (int i = 0; i < numParticles; ++i) |
|
|
asset->shapeIndices[i] = i; |
|
|
|
|
|
|
|
|
asset->shapeCenters = new float[4]; |
|
|
asset->shapeCenters[0] = center.x; |
|
|
asset->shapeCenters[1] = center.y; |
|
|
asset->shapeCenters[2] = center.z; |
|
|
|
|
|
asset->shapePlasticThresholds = NULL; |
|
|
asset->shapePlasticCreeps = NULL; |
|
|
|
|
|
asset->shapeCoefficients = new float[1]; |
|
|
asset->shapeCoefficients[0] = 1.0f; |
|
|
|
|
|
asset->shapeOffsets = new int[1]; |
|
|
asset->shapeOffsets[0] = numParticles; |
|
|
} |
|
|
|
|
|
return asset; |
|
|
} |
|
|
|