20 changed files with 643 additions and 158 deletions
@ -0,0 +1,42 @@ |
|||
#ifndef NURBSPERFORMER_LOOP_DETECTION_CUH |
|||
#define NURBSPERFORMER_LOOP_DETECTION_CUH |
|||
|
|||
#include "device/srf_mesh.cuh" |
|||
#include "map" |
|||
#include "set" |
|||
|
|||
class LoopDetection { |
|||
public: |
|||
SrfMesh *d_s_srfMesh; |
|||
SrfMesh *d_f_srfMesh; |
|||
|
|||
float s_paramRegionSize_u; |
|||
float s_paramRegionSize_v; |
|||
|
|||
int edgeSampleCnt; |
|||
|
|||
glm::vec<2, int> *d_selectedPointsIdx; |
|||
glm::vec2 *d_vectorFields; |
|||
int *d_rotationNumbers; |
|||
|
|||
LoopDetection(glm::vec3 *s_eval, glm::vec3 *f_eval, glm::vec3 *s_tan_u, glm::vec3 *f_tan_u, glm::vec3 *s_tan_v, |
|||
glm::vec3 *f_tan_v, glm::vec3 *s_norm, glm::vec3 *f_norm, int edgeSampleCnt, |
|||
float s_paramRegionSize_u, float s_paramRegionSize_v); |
|||
|
|||
__host__ void h_initOrientedDisAndVecFields( |
|||
const std::map<std::pair<int, int>, std::set<std::pair<int, int>>> &intersectBoxPairs); |
|||
__host__ void h_getRotationNumber(); |
|||
|
|||
~LoopDetection(); |
|||
}; |
|||
|
|||
__global__ void |
|||
g_initOrientedDisAndVecFields(SrfMesh *s_srfMesh, SrfMesh *f_srfMesh, int s_cellCnt, glm::vec<2, int> *s_cells, |
|||
glm::vec<2, int> **f_cells, const int *f_cellCnt, glm::vec<2, int> *selectedPointsIdx, |
|||
glm::vec2 *vectorFields); |
|||
|
|||
__global__ void |
|||
g_getRotationNumber(SrfMesh *s_srfMesh, float paramRegionSize_u, float paramRegionSize_v, glm::vec2 *vectorFields, |
|||
int *rotationNumbers); |
|||
|
|||
#endif //NURBSPERFORMER_LOOP_DETECTION_CUH |
@ -0,0 +1,17 @@ |
|||
#ifndef NURBSPERFORMER_SRF_MESH_CUH |
|||
#define NURBSPERFORMER_SRF_MESH_CUH |
|||
|
|||
#include "glm/glm.hpp" |
|||
|
|||
class SrfMesh { |
|||
public: |
|||
int edgeSampleCnt; |
|||
glm::vec3 *evaluationRes; |
|||
glm::vec3 *tangent_u; |
|||
glm::vec3 *tangent_v; |
|||
glm::vec3 *normal; |
|||
SrfMesh(glm::vec3 *evalRes, glm::vec3 *tan_u, glm::vec3 *tan_v, glm::vec3 *nor, int edgeSampleCnt); |
|||
}; |
|||
|
|||
|
|||
#endif //NURBSPERFORMER_SRF_MESH_CUH |
@ -0,0 +1,229 @@ |
|||
#include <vector> |
|||
#include "device/Nurbs/loop_detection.cuh" |
|||
#include "utils.h" |
|||
#include "cuda_runtime.h" |
|||
#include "device/device_utils.cuh" |
|||
|
|||
LoopDetection::LoopDetection(glm::vec3 *const s_eval, glm::vec3 *const f_eval, glm::vec3 *const s_tan_u, |
|||
glm::vec3 *const f_tan_u, glm::vec3 *const s_tan_v, glm::vec3 *const f_tan_v, |
|||
glm::vec3 *const s_norm, glm::vec3 *const f_norm, int edgeSampleCnt, |
|||
float s_paramRegionSize_u, float s_paramRegionSize_v) : |
|||
edgeSampleCnt(edgeSampleCnt), |
|||
s_paramRegionSize_u(s_paramRegionSize_u), |
|||
s_paramRegionSize_v(s_paramRegionSize_v) { |
|||
auto initSrfMesh = [](SrfMesh *&d_srfMesh, glm::vec3 *eval, glm::vec3 *tan_u, glm::vec3 *tan_v, glm::vec3 *norm, |
|||
int edgeSampleCnt) { |
|||
auto h_srfMesh = new SrfMesh(eval, tan_u, tan_v, norm, edgeSampleCnt); |
|||
safeCudaFree(d_srfMesh); |
|||
auto srfMeshSize = sizeof(SrfMesh); |
|||
cudaMalloc((void **) &d_srfMesh, srfMeshSize); |
|||
cudaMemcpy(d_srfMesh, h_srfMesh, srfMeshSize, cudaMemcpyHostToDevice); |
|||
safeFree(h_srfMesh); |
|||
}; |
|||
initSrfMesh(d_s_srfMesh, s_eval, s_tan_u, s_tan_v, s_norm, edgeSampleCnt); |
|||
initSrfMesh(d_f_srfMesh, f_eval, f_tan_u, f_tan_v, f_norm, edgeSampleCnt); |
|||
} |
|||
|
|||
|
|||
LoopDetection::~LoopDetection() { |
|||
safeCudaFree(d_selectedPointsIdx); |
|||
safeCudaFree(d_vectorFields); |
|||
safeCudaFree(d_s_srfMesh); |
|||
safeCudaFree(d_f_srfMesh); |
|||
safeCudaFree(d_rotationNumbers); |
|||
} |
|||
|
|||
__host__ void LoopDetection::h_initOrientedDisAndVecFields( |
|||
const std::map<std::pair<int, int>, std::set<std::pair<int, int>>> &intersectBoxPairs) { |
|||
int sampleCnt = edgeSampleCnt * edgeSampleCnt; |
|||
|
|||
safeCudaFree(d_selectedPointsIdx); |
|||
auto selectedPointsIdxVec = std::vector<glm::vec2>(sampleCnt, glm::vec<2, int>(-1, -1)); |
|||
auto h_selectedPointsIdx = new glm::vec<2, int>[sampleCnt]; |
|||
std::copy(selectedPointsIdxVec.begin(), selectedPointsIdxVec.end(), h_selectedPointsIdx); |
|||
int selectedPtsIdxBytes = sizeof(glm::vec<2, int>) * sampleCnt; |
|||
cudaMalloc((void**)&d_selectedPointsIdx, selectedPtsIdxBytes); |
|||
cudaMemcpy(d_selectedPointsIdx, h_selectedPointsIdx, selectedPtsIdxBytes, cudaMemcpyHostToDevice); |
|||
|
|||
safeCudaFree(d_vectorFields); |
|||
cudaMalloc((void**)&d_vectorFields, sizeof(glm::vec2) * sampleCnt); |
|||
|
|||
int mapCnt = intersectBoxPairs.size(); |
|||
|
|||
auto *h_s_cells = new glm::vec<2, int>[mapCnt]; |
|||
glm::vec<2, int> *d_s_cells; |
|||
auto **h_f_cells = new glm::vec<2, int> *[mapCnt]; |
|||
glm::vec<2, int> **d_f_cells; |
|||
auto *h_f_cellsCnt = new int[mapCnt]; |
|||
int *d_f_cellsCnt; |
|||
int i = 0; |
|||
for (const auto &boxPair: intersectBoxPairs) { |
|||
h_s_cells[i] = glm::vec<2, int>(boxPair.first.first, boxPair.first.second); |
|||
h_f_cellsCnt[i] = boxPair.second.size(); |
|||
auto h_f_cellsTmp = new glm::vec<2, int>[h_f_cellsCnt[i]]; |
|||
int j = 0; |
|||
for (auto box: boxPair.second) { |
|||
h_f_cellsTmp[j] = glm::vec<2, int>(box.first, box.second); |
|||
j++; |
|||
} |
|||
auto f_relatedCellsBytes = sizeof(glm::vec<2, int>) * h_f_cellsCnt[i]; |
|||
cudaMalloc((void **) &h_f_cells[i], f_relatedCellsBytes); |
|||
cudaMemcpy(h_f_cells[i], h_f_cellsTmp, f_relatedCellsBytes, cudaMemcpyHostToDevice); |
|||
free(h_f_cellsTmp); |
|||
i++; |
|||
} |
|||
|
|||
int s_cellsBytes = sizeof(glm::vec<2, int>) * mapCnt; |
|||
cudaMalloc((void **) &d_s_cells, s_cellsBytes); |
|||
cudaMemcpy(d_s_cells, h_s_cells, s_cellsBytes, cudaMemcpyHostToDevice); |
|||
|
|||
int f_cellsPtrBytes = sizeof(glm::vec<2, int>) * mapCnt; |
|||
cudaMalloc((void **) &d_f_cells, f_cellsPtrBytes); |
|||
cudaMemcpy(d_f_cells, h_f_cells, f_cellsPtrBytes, cudaMemcpyHostToDevice); |
|||
|
|||
int f_cellsCntBytes = sizeof(int) * mapCnt; |
|||
cudaMalloc((void **) &d_f_cellsCnt, f_cellsCntBytes); |
|||
cudaMemcpy(d_f_cellsCnt, h_f_cellsCnt, f_cellsCntBytes, cudaMemcpyHostToDevice); |
|||
|
|||
dim3 block(64, 64); |
|||
dim3 grid((mapCnt + block.x * block.y - 1) / (block.x * block.y)); |
|||
g_initOrientedDisAndVecFields <<< grid, block >>>(d_s_srfMesh, d_f_srfMesh, mapCnt, d_s_cells, d_f_cells, |
|||
d_f_cellsCnt, d_selectedPointsIdx, d_vectorFields); |
|||
|
|||
cudaFree(d_s_cells); |
|||
cudaFree(d_f_cells); |
|||
cudaFree(d_f_cellsCnt); |
|||
for (int k = 0; k < mapCnt; k++) { |
|||
cudaFree(h_f_cells[k]); |
|||
} |
|||
free(h_s_cells); |
|||
free(h_f_cells); |
|||
free(h_f_cellsCnt); |
|||
free(h_selectedPointsIdx); |
|||
} |
|||
|
|||
__host__ void LoopDetection::h_getRotationNumber() { |
|||
safeCudaFree(d_rotationNumbers); |
|||
cudaMalloc((void**)&d_rotationNumbers, sizeof(int) * edgeSampleCnt * edgeSampleCnt); |
|||
|
|||
dim3 block(32, 32); |
|||
dim3 grid((edgeSampleCnt + block.x - 1) / block.x, (edgeSampleCnt + block.y - 1) / block.y); |
|||
g_getRotationNumber<<<grid, block>>>(d_s_srfMesh, s_paramRegionSize_u, s_paramRegionSize_v, d_vectorFields, |
|||
d_rotationNumbers); |
|||
|
|||
} |
|||
|
|||
__device__ const int neighborIdxes[4][2] = {{1, 0}, |
|||
{0, 1}, |
|||
{-1, 0}, |
|||
{0, -1}}; |
|||
|
|||
__device__ const int dirs[2][2][2] = {{{-1, 1}, {1, 1}}, |
|||
{{-1, -1}, {1, -1}}}; // 必须是左上,右上,左下,右下的顺序 |
|||
|
|||
__global__ void |
|||
g_initOrientedDisAndVecFields(SrfMesh *s_srfMesh, SrfMesh *f_srfMesh, int s_cellCnt, glm::vec<2, int> *s_cells, |
|||
glm::vec<2, int> **f_cells, const int *f_cellCnt, glm::vec<2, int> *selectedPointsIdx, |
|||
glm::vec2 *vectorFields) { |
|||
// // 二维的grid和一维的block |
|||
// int idx = (blockIdx.y * gridDim.x + blockIdx.x) * blockDim.x * blockDim.y + threadIdx.x; |
|||
// 一维的grid和二维的block |
|||
int idx = blockIdx.x * blockDim.x * blockDim.y + threadIdx.y * blockDim.x + threadIdx.x; |
|||
if (idx >= s_cellCnt) return; |
|||
// printf("idx: %d\n", idx); |
|||
if (idx == 0) printf("<%d, %d>, %f\n", neighborIdxes[0][0], neighborIdxes[0][1], -D_FLT_MAX); |
|||
int s_edgeSampleCnt = s_srfMesh->edgeSampleCnt; |
|||
int f_edgeSampleCnt = f_srfMesh->edgeSampleCnt; |
|||
for (auto neighborIdx: neighborIdxes) { |
|||
for (int i = 0; i < 2; i++) { |
|||
for (int j = 0; j < 2; j++) { |
|||
float minDis = -D_FLT_MAX; |
|||
int minDisFIdx_u = -1, minDisFIdx_v = -1; |
|||
int idxI = s_cells[idx].x + i + neighborIdx[0]; |
|||
int idxJ = s_cells[idx].y + j + neighborIdx[1]; |
|||
if (idxI < 0 || idxI >= s_edgeSampleCnt || idxJ < 0 || idxJ >= s_edgeSampleCnt || |
|||
selectedPointsIdx[idxI * s_edgeSampleCnt + idxJ] != glm::vec<2, int>(2, 2)) { |
|||
// 尽量不重复计算 |
|||
// 但在多线程情况下,这样还是可以能重复计算 |
|||
continue; |
|||
} |
|||
for (int fi = 0; fi < f_cellCnt[idx]; fi++) { |
|||
for (int k = 0; k < 2; k++) { |
|||
for (int l = 0; l < 2; l++) { |
|||
for (int step_u = 0; step_u <= 2; step_u++) { |
|||
for (int step_v = 0; step_v + step_u <= 2; step_v++) { |
|||
int fIdx_u = f_cells[idx][fi].x + k + step_u * dirs[k][l][0]; |
|||
int fIdx_v = f_cells[idx][fi].y + l + step_v * dirs[k][l][1]; |
|||
if (fIdx_u < 0 || fIdx_u >= f_edgeSampleCnt || fIdx_v < 0 || |
|||
fIdx_v >= f_edgeSampleCnt) |
|||
continue; |
|||
auto dis = glm::distance(s_srfMesh->evaluationRes[idxI][idxJ], |
|||
f_srfMesh->evaluationRes[fIdx_u][fIdx_v]); |
|||
if (dis < minDis) { |
|||
minDis = dis; |
|||
minDisFIdx_u = fIdx_u; |
|||
minDisFIdx_v = fIdx_v; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
selectedPointsIdx[idxI * s_edgeSampleCnt + idxJ] = glm::vec<2, int>(minDisFIdx_u, minDisFIdx_v); |
|||
auto n2 = f_srfMesh->normal[minDisFIdx_u * f_edgeSampleCnt + minDisFIdx_v]; |
|||
auto ps_pu = s_srfMesh->tangent_u[idxI * s_edgeSampleCnt + idxJ]; |
|||
auto ps_pv = s_srfMesh->tangent_v[idxI * s_edgeSampleCnt + idxJ]; |
|||
vectorFields[idxI * s_edgeSampleCnt + idxJ] = glm::vec2(glm::dot(n2, ps_pu), glm::dot(n2, ps_pv)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
__global__ void |
|||
g_getRotationNumber(SrfMesh *s_srfMesh, float paramRegionSize_u, float paramRegionSize_v, glm::vec2 *vectorFields, |
|||
int *rotationNumbers) { |
|||
// 二维grid和二维的block |
|||
int ix = blockIdx.x * blockDim.x + threadIdx.x; |
|||
int iy = blockIdx.y * blockDim.y + threadIdx.y; |
|||
int s_edgeSampleCnt = s_srfMesh->edgeSampleCnt; |
|||
float F[2][2], G[2][2]; |
|||
for (int biasI = 0; biasI < 2; biasI++) { |
|||
for (int biasJ = 0; biasJ < 2; biasJ++) { |
|||
auto idxI = ix + biasI; |
|||
auto idxJ = iy + biasJ; |
|||
auto v = vectorFields[idxI * s_edgeSampleCnt + idxJ]; |
|||
auto vSquareSum = v.x * v.x + v.y * v.y; |
|||
auto pTheta_pChi = -v.y / vSquareSum; |
|||
auto pTheta_pPhi = v.x / vSquareSum; |
|||
// auto pChi_pu = |
|||
// (vectorFields[idxI + 1][idxJ].x - vectorFields[idxI - 1][idxJ].x) / (2 * uParamCellSize); |
|||
// auto pChi_pv = |
|||
// (vectorFields[idxI][idxJ + 1].x - vectorFields[idxI][idxJ - 1].x) / (2 * vParamCellSize); |
|||
glm::vec2 pV_pu; |
|||
glm::vec2 pV_pv; |
|||
if (idxI == 0) |
|||
pV_pu = (vectorFields[(idxI + 1) * s_edgeSampleCnt + idxJ] - |
|||
vectorFields[idxI * s_edgeSampleCnt + idxJ]) / paramRegionSize_u; |
|||
else if (idxI == s_edgeSampleCnt - 1) |
|||
pV_pu = (vectorFields[idxI * s_edgeSampleCnt + idxJ] - |
|||
vectorFields[(idxI - 1) * s_edgeSampleCnt + idxJ]) / paramRegionSize_u; |
|||
else |
|||
pV_pu = (vectorFields[(idxI + 1) * s_edgeSampleCnt + idxJ] - |
|||
vectorFields[(idxI - 1) * s_edgeSampleCnt + idxJ]) / (2 * paramRegionSize_u); |
|||
if (idxJ == 0) |
|||
pV_pv = (vectorFields[idxI * s_edgeSampleCnt + idxJ + 1] - |
|||
vectorFields[idxI * s_edgeSampleCnt + idxJ]) / paramRegionSize_v; |
|||
else if (idxJ == s_edgeSampleCnt - 1) |
|||
pV_pv = (vectorFields[idxI * s_edgeSampleCnt + idxJ] - |
|||
vectorFields[idxI * s_edgeSampleCnt + idxJ - 1]) / paramRegionSize_v; |
|||
else |
|||
pV_pv = (vectorFields[idxI * s_edgeSampleCnt + idxJ + 1] - |
|||
vectorFields[idxI * s_edgeSampleCnt + idxJ - 1]) / (2 * paramRegionSize_v); |
|||
F[biasI][biasJ] = pTheta_pChi * pV_pu.x + pTheta_pPhi * pV_pu.y; |
|||
G[biasI][biasJ] = pTheta_pChi * pV_pv.x + pTheta_pPhi * pV_pv.y; |
|||
} |
|||
} |
|||
rotationNumbers[ix * s_edgeSampleCnt + iy] = int( |
|||
round(((F[0][1] + F[1][1] - F[0][0] - F[1][0]) * paramRegionSize_u + |
|||
(G[0][0] + G[0][1] - G[1][0] - G[1][1]) * paramRegionSize_v)) / 2.); |
|||
} |
@ -0,0 +1,4 @@ |
|||
#include "device/srf_mesh.cuh" |
|||
|
|||
SrfMesh::SrfMesh(glm::vec3 *evalRes, glm::vec3 *tan_u, glm::vec3 *tan_v, glm::vec3 *nor, int edgeSampleCnt) : |
|||
evaluationRes(evalRes), tangent_u(tan_u), tangent_v(tan_v), normal(nor), edgeSampleCnt(edgeSampleCnt) {} |
Loading…
Reference in new issue