public void runClassifyVoxel() { var gpu = Gpu.Default; samplePts = ConvertPointsToFloat3(samplePoints); // allocate memorys var d_voxelVerts = gpu.Allocate <int>(numVoxels); float3[] d_samplePts = gpu.Allocate <float3>(samplePts); //Copy const values float3 baseP = new float3((float)basePoint.X, (float)basePoint.Y, (float)basePoint.Z); gpu.Copy(isoValue, constIsovalue); gpu.Copy(fusion, constFusion); gpu.Copy(baseP, constBasePoint); gpu.Copy(voxelSize, constVoxelSize); gpu.Copy(gridSize, constGridSize); gpu.Copy(Tables.VertsTable, verticesTable); gpu.For(0, numVoxels, i => ClassifyVoxel(i, d_samplePts, d_voxelVerts)); voxelVerts = Gpu.CopyToHost(d_voxelVerts); Gpu.Free(d_samplePts); Gpu.Free(d_voxelVerts); }
public void ClassifyVoxel(deviceptr <int3> d_gridIdx, deviceptr <float3> d_voxelV, deviceptr <int> d_voxelVerts, deviceptr <int> d_voxelOccupied, deviceptr <float3> d_samplePts, int sampleLength) { int blockId = blockIdx.y * gridDim.x + blockIdx.x; //block在grid中的位置 int i = blockId * blockDim.x + threadIdx.x; //线程索引 // compute 3d index in the grid int3 gridPos = calcGridPos(i, constGridSize.Value); d_gridIdx[i] = gridPos; float3 p = new float3(); p.x = constBasePoint.Value.x + gridPos.x * constVoxelSize.Value.x; p.y = constBasePoint.Value.y + gridPos.y * constVoxelSize.Value.y; p.z = constBasePoint.Value.z + gridPos.z * constVoxelSize.Value.z; // compute all vertices d_voxelV[i * 8] = p; d_voxelV[i * 8 + 1] = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, 0 + p.z); d_voxelV[i * 8 + 2] = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, 0 + p.z); d_voxelV[i * 8 + 3] = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, 0 + p.z); d_voxelV[i * 8 + 4] = CreateFloat3(0 + p.x, 0 + p.y, constVoxelSize.Value.z + p.z); d_voxelV[i * 8 + 5] = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, constVoxelSize.Value.z + p.z); d_voxelV[i * 8 + 6] = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z); d_voxelV[i * 8 + 7] = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z); // compute cube value of each vertex float d0 = ComputeValue(d_samplePts, d_voxelV[i * 8], sampleLength); float d1 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 1], sampleLength); float d2 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 2], sampleLength); float d3 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 3], sampleLength); float d4 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 4], sampleLength); float d5 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 5], sampleLength); float d6 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 6], sampleLength); float d7 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 7], sampleLength); // check their status int cubeindex; cubeindex = Compact(d0, constIsovalue.Value); cubeindex += Compact(d1, constIsovalue.Value) * 2; cubeindex += Compact(d2, constIsovalue.Value) * 4; cubeindex += Compact(d3, constIsovalue.Value) * 8; cubeindex += Compact(d4, constIsovalue.Value) * 16; cubeindex += Compact(d5, constIsovalue.Value) * 32; cubeindex += Compact(d6, constIsovalue.Value) * 64; cubeindex += Compact(d7, constIsovalue.Value) * 128; //find out the number of vertices in each voxel int numVerts = verticesTable[cubeindex]; d_voxelVerts[i] = numVerts; if (numVerts > 0) { d_voxelOccupied[i] = 1; } }
public float3 CreateFloat3(float x, float y, float z) { float3 p = new float3(); p.x = x; p.y = y; p.z = z; return(p); }
private float3[] ConvertPointsToFloat3(Point3d[] pts) { float3[] d = new float3[pts.Length]; for (int i = 0; i < pts.Length; i++) { d[i].x = (float)pts[i].X; d[i].y = (float)pts[i].Y; d[i].z = (float)pts[i].Z; } return(d); }
// classify all voxels according to their activity public void ClassifyVoxel(int i, float3[] d_samplePts, int[] d_voxelVerts) { //计算grid中的位置 int3 gridPos = calcGridPos(i, constGridSize.Value); float3 p = new float3(); p.x = constBasePoint.Value.x + gridPos.x * constVoxelSize.Value.x; p.y = constBasePoint.Value.y + gridPos.y * constVoxelSize.Value.y; p.z = constBasePoint.Value.z + gridPos.z * constVoxelSize.Value.z; //输出所有顶点 float3 a0 = p; float3 a1 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, 0 + p.z); float3 a2 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, 0 + p.z); float3 a3 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, 0 + p.z); float3 a4 = CreateFloat3(0 + p.x, 0 + p.y, constVoxelSize.Value.z + p.z); float3 a5 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, constVoxelSize.Value.z + p.z); float3 a6 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z); float3 a7 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z); float distance = constVoxelSize.Value.x * constVoxelSize.Value.x + constVoxelSize.Value.y * constVoxelSize.Value.y + constVoxelSize.Value.z * constVoxelSize.Value.z; float radius = distance * constFusion.Value; //计算cube中的8个点对应的value float d0 = ComputeValue(d_samplePts, a0, d_samplePts.Length, constFusion.Value, radius); float d1 = ComputeValue(d_samplePts, a1, d_samplePts.Length, constFusion.Value, radius); float d2 = ComputeValue(d_samplePts, a2, d_samplePts.Length, constFusion.Value, radius); float d3 = ComputeValue(d_samplePts, a3, d_samplePts.Length, constFusion.Value, radius); float d4 = ComputeValue(d_samplePts, a4, d_samplePts.Length, constFusion.Value, radius); float d5 = ComputeValue(d_samplePts, a5, d_samplePts.Length, constFusion.Value, radius); float d6 = ComputeValue(d_samplePts, a6, d_samplePts.Length, constFusion.Value, radius); float d7 = ComputeValue(d_samplePts, a7, d_samplePts.Length, constFusion.Value, radius); //判定它们的状态 int cubeindex; cubeindex = Compact(d0, constIsovalue.Value); cubeindex += Compact(d1, constIsovalue.Value) * 2; cubeindex += Compact(d2, constIsovalue.Value) * 4; cubeindex += Compact(d3, constIsovalue.Value) * 8; cubeindex += Compact(d4, constIsovalue.Value) * 16; cubeindex += Compact(d5, constIsovalue.Value) * 32; cubeindex += Compact(d6, constIsovalue.Value) * 64; cubeindex += Compact(d7, constIsovalue.Value) * 128; //根据表来查出该体素的顶点数 int vertexNum = verticesTable[cubeindex]; d_voxelVerts[i] = vertexNum; }
public float ComputeValue(deviceptr <float3> samplePts, float3 testP, int sampleLength) { float result = 0.0f; float Dx, Dy, Dz; for (int j = 0; j < sampleLength; j++) { Dx = testP.x - samplePts[j].x; Dy = testP.y - samplePts[j].y; Dz = testP.z - samplePts[j].z; result += 1 / (Dx * Dx + Dy * Dy + Dz * Dz); } return(result); }
public float ComputeValue(float3[] samplePts, float3 testP, int sampleLength, float fusion, float radius) { float result = 0.0f; float Dx, Dy, Dz; for (int j = 0; j < sampleLength; j++) { Dx = testP.x - samplePts[j].x; Dy = testP.y - samplePts[j].y; Dz = testP.z - samplePts[j].z; // very slow field function // result += 1.0f / (Dx * Dx + Dy * Dy + Dz * Dz); // field function of soft object float di = Dx * Dx + Dy * Dy + Dz * Dz; if (di <= radius) { float a = di / radius; result += (1.0f - (a * a * a * a * a * a * 4.0f / 9.0f) + (a * a * a * a * 17.0f / 9.0f) - (a * a * 22.0f / 9.0f)); } } return(result); }
public void ExtractIsoSurface(deviceptr <float> d_cubeValues, deviceptr <float3> d_pts, deviceptr <float3> Apts, deviceptr <int3> d_index3d_voxelActive, deviceptr <float3> d_model_voxelActive, deviceptr <float3> d_samplePts, deviceptr <int> d_verts_scanIdx, int sampleLength) { int blockId = blockIdx.y * gridDim.x + blockIdx.x; int i = blockId * blockDim.x + threadIdx.x; //Compute cubeValues of 8 vertices d_cubeValues[i * 8] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8], sampleLength); d_cubeValues[i * 8 + 1] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 1], sampleLength); d_cubeValues[i * 8 + 2] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 2], sampleLength); d_cubeValues[i * 8 + 3] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 3], sampleLength); d_cubeValues[i * 8 + 4] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 4], sampleLength); d_cubeValues[i * 8 + 5] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 5], sampleLength); d_cubeValues[i * 8 + 6] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 6], sampleLength); d_cubeValues[i * 8 + 7] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 7], sampleLength); //Check each vertex state int flag = Compact(d_cubeValues[i * 8], constIsovalue.Value); flag += Compact(d_cubeValues[i * 8 + 1], constIsovalue.Value) * 2; flag += Compact(d_cubeValues[i * 8 + 2], constIsovalue.Value) * 4; flag += Compact(d_cubeValues[i * 8 + 3], constIsovalue.Value) * 8; flag += Compact(d_cubeValues[i * 8 + 4], constIsovalue.Value) * 16; flag += Compact(d_cubeValues[i * 8 + 5], constIsovalue.Value) * 32; flag += Compact(d_cubeValues[i * 8 + 6], constIsovalue.Value) * 64; flag += Compact(d_cubeValues[i * 8 + 7], constIsovalue.Value) * 128; //find out which edge intersects the isosurface int EdgeFlag = edgeTable[flag]; //check whether this voxel is crossed by the isosurface for (int j = 0; j < 12; j++) { //check whether an edge have a point if ((EdgeFlag & (1 << j)) != 0) { //compute t values from two end points on each edge float Offset = GetOffset(d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 0]], d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 1]], constIsovalue.Value); float3 pt = new float3(); //get positions pt.x = constBasePoint.Value.x + (d_index3d_voxelActive[i].x + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 0] + Offset * constEdgeDirection[j * 3 + 0]) * constScale.Value; pt.y = constBasePoint.Value.y + (d_index3d_voxelActive[i].y + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 1] + Offset * constEdgeDirection[j * 3 + 1]) * constScale.Value; pt.z = constBasePoint.Value.z + (d_index3d_voxelActive[i].z + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 2] + Offset * constEdgeDirection[j * 3 + 2]) * constScale.Value; d_pts[12 * i + j] = pt; } } int num = 0; //Find out points from each triangle for (int Triangle = 0; Triangle < 5; Triangle++) { if (triangleTable[flag * 16 + 3 * Triangle] < 0) { break; } for (int Corner = 0; Corner < 3; Corner++) { int Vertex = triangleTable[flag * 16 + 3 * Triangle + Corner]; float3 pd = CreateFloat3(d_pts[12 * i + Vertex].x, d_pts[12 * i + Vertex].y, d_pts[12 * i + Vertex].z); Apts[d_verts_scanIdx[i] + num] = pd; num++; } } }
// extract isosurface points using GPU public List <Point3f> runExtractIsoSurfaceGPU() { var gpu = Gpu.Default; // output arguments float3[] pts = new float3[12 * num_voxelActive]; float3[] d_pts = Gpu.Default.Allocate <float3>(pts); float3[] d_resultV = Gpu.Default.Allocate <float3>(sumVerts); float[] d_cubeValues = Gpu.Default.Allocate <float>(8 * num_voxelActive); // input arguments float3[] d_samplePts = Gpu.Default.Allocate <float3>(samplePts); int[] d_verts_scanIdx = Gpu.Default.Allocate <int>(verts_scanIdx); int[] d_index_voxelActive = Gpu.Default.Allocate <int>(index_voxelActive); // const values gpu.Copy(Vertices, constVertices); gpu.Copy(EdgeDirection, constEdgeDirection); gpu.Copy(EdgeConnection, constEdgeConnection); gpu.Copy(Tables.EdgeTable, edgeTable); gpu.Copy(Tables.TriangleTable_GPU, triangleTable); float3 baseP = new float3((float)basePoint.X, (float)basePoint.Y, (float)basePoint.Z); gpu.Copy(baseP, constBasePoint); gpu.Copy(isoValue, constIsovalue); gpu.Copy(scale, constScale); gpu.For(0, num_voxelActive, i => { //计算grid中的位置 int3 gridPos = calcGridPos(d_index_voxelActive[i], constGridSize.Value); float3 p = new float3(); p.x = constBasePoint.Value.x + gridPos.x * constVoxelSize.Value.x; p.y = constBasePoint.Value.y + gridPos.y * constVoxelSize.Value.y; p.z = constBasePoint.Value.z + gridPos.z * constVoxelSize.Value.z; //输出所有顶点 float3 a0 = p; float3 a1 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, 0 + p.z); float3 a2 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, 0 + p.z); float3 a3 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, 0 + p.z); float3 a4 = CreateFloat3(0 + p.x, 0 + p.y, constVoxelSize.Value.z + p.z); float3 a5 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, constVoxelSize.Value.z + p.z); float3 a6 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z); float3 a7 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z); float distance = constVoxelSize.Value.x * constVoxelSize.Value.x + constVoxelSize.Value.y * constVoxelSize.Value.y + constVoxelSize.Value.z * constVoxelSize.Value.z; float radius = distance * constFusion.Value; //Compute cubeValues of 8 vertices d_cubeValues[i * 8] = ComputeValue(d_samplePts, a0, d_samplePts.Length, constFusion.Value, radius); d_cubeValues[i * 8 + 1] = ComputeValue(d_samplePts, a1, d_samplePts.Length, constFusion.Value, radius); d_cubeValues[i * 8 + 2] = ComputeValue(d_samplePts, a2, d_samplePts.Length, constFusion.Value, radius); d_cubeValues[i * 8 + 3] = ComputeValue(d_samplePts, a3, d_samplePts.Length, constFusion.Value, radius); d_cubeValues[i * 8 + 4] = ComputeValue(d_samplePts, a4, d_samplePts.Length, constFusion.Value, radius); d_cubeValues[i * 8 + 5] = ComputeValue(d_samplePts, a5, d_samplePts.Length, constFusion.Value, radius); d_cubeValues[i * 8 + 6] = ComputeValue(d_samplePts, a6, d_samplePts.Length, constFusion.Value, radius); d_cubeValues[i * 8 + 7] = ComputeValue(d_samplePts, a7, d_samplePts.Length, constFusion.Value, radius); //Check each vertex state int flag = Compact(d_cubeValues[i * 8], constIsovalue.Value); flag += Compact(d_cubeValues[i * 8 + 1], constIsovalue.Value) * 2; flag += Compact(d_cubeValues[i * 8 + 2], constIsovalue.Value) * 4; flag += Compact(d_cubeValues[i * 8 + 3], constIsovalue.Value) * 8; flag += Compact(d_cubeValues[i * 8 + 4], constIsovalue.Value) * 16; flag += Compact(d_cubeValues[i * 8 + 5], constIsovalue.Value) * 32; flag += Compact(d_cubeValues[i * 8 + 6], constIsovalue.Value) * 64; flag += Compact(d_cubeValues[i * 8 + 7], constIsovalue.Value) * 128; //find out which edge intersects the isosurface int EdgeFlag = edgeTable[flag]; //check whether this voxel is crossed by the isosurface for (int j = 0; j < 12; j++) { //check whether an edge have a point if ((EdgeFlag & (1 << j)) != 0) { //compute t values from two end points on each edge float Offset = GetOffset(d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 0]], d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 1]], constIsovalue.Value); float3 pt = new float3(); //get positions pt.x = constBasePoint.Value.x + (gridPos.x + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 0] + Offset * constEdgeDirection[j * 3 + 0]) * constScale.Value; pt.y = constBasePoint.Value.y + (gridPos.y + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 1] + Offset * constEdgeDirection[j * 3 + 1]) * constScale.Value; pt.z = constBasePoint.Value.z + (gridPos.z + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 2] + Offset * constEdgeDirection[j * 3 + 2]) * constScale.Value; d_pts[12 * i + j] = pt; } } int num = 0; //Find out points from each triangle for (int Triangle = 0; Triangle < 5; Triangle++) { if (triangleTable[flag * 16 + 3 * Triangle] < 0) { break; } for (int Corner = 0; Corner < 3; Corner++) { int Vertex = triangleTable[flag * 16 + 3 * Triangle + Corner]; float3 pd = CreateFloat3(d_pts[12 * i + Vertex].x, d_pts[12 * i + Vertex].y, d_pts[12 * i + Vertex].z); d_resultV[d_verts_scanIdx[i] + num] = pd; num++; } } }); resultVerts = Gpu.CopyToHost(d_resultV); Gpu.Free(d_resultV); Gpu.Free(d_pts); Gpu.Free(d_samplePts); Gpu.Free(d_verts_scanIdx); Gpu.Free(d_index_voxelActive); return(ConvertFloat3ToPoint3f(resultVerts)); }