| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -7,6 +7,7 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "utils.h" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "device/Nurbs/bvh.cuh" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "device/device_utils.cuh" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "tinynurbs/tinynurbs.h" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__global__ void | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					NurbsSurface::g_evaluate(float *res, const float *d_nTexture_u, const float *d_nTexture_v, const float *d_points, | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -266,8 +267,8 @@ NurbsSurface::g_curvature(const float *derivatives, const int sampleCnt_u, const | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ NurbsSurface::Surface::Surface(std::vector<std::vector<std::vector<float>>> controlPoints, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                        std::vector<float> knots_u, std::vector<float> knots_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ NurbsSurface::Surface::Surface(MeshPoints4 controlPoints, std::vector<float> knots_u, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                        std::vector<float> knots_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    this->knots_u = std::move(knots_u); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    this->knots_v = std::move(knots_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    this->controlPoints = std::move(controlPoints); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -284,24 +285,22 @@ __host__ NurbsSurface::Surface::Surface(std::vector<std::vector<std::vector<floa | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    d_k = nullptr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    d_normals = nullptr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bvh.nodes = nullptr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    h_evaluations = nullptr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    h_derivatives = nullptr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    h_normals = nullptr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ std::vector<std::vector<std::vector<float>>> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					NurbsSurface::Surface::evaluate(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (POINT_SIZE != controlPoints[0][0].size()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        printf("Error! Nurbs控制点应表示为长度为4的齐次坐标\n"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return {}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void NurbsSurface::Surface::evaluate(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 构造指向device的controlPoints | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const int pointsCnt_u = controlPoints.size(), pointsCnt_v = controlPoints[0].size(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const int pointsBytes = pointsCnt_u * pointsCnt_v * POINT_SIZE * sizeof(float); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const int pointsBytes = pointsCnt_u * pointsCnt_v * sizeof(glm::vec4); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto *h_points = (float *) malloc(pointsBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for (int i = 0; i < pointsCnt_u; i++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (int j = 0; j < pointsCnt_v; j++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for (int k = 0; k < POINT_SIZE; k++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                h_points[(i * pointsCnt_v + j) * POINT_SIZE + k] = controlPoints[i][j][k]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//            printf("%f/ %f/ %f/ %f     ", controlPoints[i][j][0], controlPoints[i][j][1], controlPoints[i][j][2], controlPoints[i][j][3]); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_points, pointsBytes); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -314,6 +313,8 @@ NurbsSurface::Surface::evaluate(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for (int i = 0; i < knotsCnt_u; i++) h_knots_u[i] = knots_u[i]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for (int i = 0; i < knotsCnt_v; i++) h_knots_v[i] = knots_v[i]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeCudaFree(d_knots_u); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeCudaFree(d_knots_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_knots_u, knotsBytes_u); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_knots_v, knotsBytes_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMemcpy(d_knots_u, h_knots_u, knotsBytes_u, cudaMemcpyHostToDevice); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -330,10 +331,10 @@ NurbsSurface::Surface::evaluate(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 结果数组 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    size_t resBytes = sampleCnt_u * sampleCnt_v * 3 * sizeof(float); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeCudaFree(d_evaluationRes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_evaluationRes, resBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto *h_res = (float *) malloc(resBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_evaluations); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    h_evaluations = (float *) malloc(resBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 构造g_basisTexture线程层级 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    dim3 blockBasis(512); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -354,8 +355,8 @@ NurbsSurface::Surface::evaluate(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaDeviceSynchronize(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    g_evaluate <<<grid, block>>>(d_evaluationRes, d_nTexture_u, d_nTexture_v, d_points, pointsCnt_u, pointsCnt_v, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                 POINT_SIZE, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                 knots_u[knotsCnt_u - 1], knots_v[knotsCnt_v - 1], sampleCnt_u, sampleCnt_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                 POINT_SIZE, knots_u[knotsCnt_u - 1], knots_v[knotsCnt_v - 1], sampleCnt_u, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                 sampleCnt_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaDeviceSynchronize(); // 所用线程结束后再获取结束时间。cudaThreadSynchronize()在CUDA1.0后被弃用 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (recordTime) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        time_cost_device = get_time() - time_cost_device; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -363,34 +364,58 @@ NurbsSurface::Surface::evaluate(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					               time_cost_device); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMemcpy(h_res, d_evaluationRes, resBytes, cudaMemcpyDeviceToHost); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<std::vector<std::vector<float>>> res(sampleCnt_u, std::vector<std::vector<float>>(sampleCnt_v, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                                                  std::vector<float>(3, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                                                                     0.))); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMemcpy(h_evaluations, d_evaluationRes, resBytes, cudaMemcpyDeviceToHost); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 释放内存 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_points); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_knots_u); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_knots_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ std::vector<std::vector<glm::vec3>> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					NurbsSurface::Surface::getEvaluateVec(int sampleCnt_u, int sampleCnt_v) const { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<std::vector<glm::vec3>> res(sampleCnt_u, std::vector<glm::vec3>(sampleCnt_v, glm::vec3())); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for (int i = 0; i < sampleCnt_u; i++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        int baseIdx = i * sampleCnt_v * 3; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (int j = 0; j < sampleCnt_v; j++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            baseIdx += j * 3; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            res[i][j][0] = h_res[baseIdx]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            res[i][j][1] = h_res[baseIdx + 1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            res[i][j][2] = h_res[baseIdx + 2]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            res[i][j].x = h_evaluations[baseIdx]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            res[i][j].y = h_evaluations[baseIdx + 1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            res[i][j].z = h_evaluations[baseIdx + 2]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//            printf("%d, %d: %f, %f, %f\n", i, j, res[i][j][0], res[i][j][1], res[i][j][2]); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 释放内存 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_points); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_knots_u); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_knots_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_res); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return res; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void NurbsSurface::Surface::derivative(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 先完成evaluation | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    evaluate(sampleCnt_u, sampleCnt_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ std::vector<MeshPoints3> NurbsSurface::Surface::getDerivativeVec(int sampleCnt_u, int sampleCnt_v) const { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    MeshPoints3 der_u(sampleCnt_u, LinePoints3(sampleCnt_v)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    MeshPoints3 der_v(sampleCnt_u, LinePoints3(sampleCnt_v)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    MeshPoints3 normal(sampleCnt_u, LinePoints3(sampleCnt_v)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for (int i = 0; i < sampleCnt_u; i++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        int baseIdx = i * sampleCnt_v * 6; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (int j = 0; j < sampleCnt_v; j++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            baseIdx += j * 6; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            der_u[i][j].x = h_derivatives[baseIdx]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            der_u[i][j].y = h_derivatives[baseIdx + 1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            der_u[i][j].z = h_derivatives[baseIdx + 2]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            der_v[i][j].x = h_derivatives[baseIdx + 3]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            der_v[i][j].y = h_derivatives[baseIdx + 4]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            der_v[i][j].z = h_derivatives[baseIdx + 5]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            auto baseIdxNorm = baseIdx / 2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            normal[i][j].x = h_normals[baseIdxNorm]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            normal[i][j].y = h_normals[baseIdxNorm + 1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            normal[i][j].z = h_normals[baseIdxNorm + 2]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // TODO normalize 归一化在gpu中实现! | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            normal[i][j] = glm::normalize(normal[i][j]); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return {der_u, der_v, normal}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void NurbsSurface::Surface::derivative(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (POINT_SIZE != controlPoints[0][0].size()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        printf("Error! Nurbs控制点应表示为长度为4的齐次坐标\n"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -405,13 +430,13 @@ __host__ void NurbsSurface::Surface::derivative(int sampleCnt_u, int sampleCnt_v | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 构造切向量计算结果 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeCudaFree(d_derivatives); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_derivatives, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					               sampleCnt_v * sampleCnt_u * 6 * sizeof(float)); // 每个采样所求的切向量是一个六元向量,前三位是对u的偏导、后三位是对v的偏导 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    size_t derBytes = sampleCnt_u * sampleCnt_v * 6 * sizeof(float); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_derivatives, derBytes); // 每个采样所求的切向量是一个六元向量,前三位是对u的偏导、后三位是对v的偏导 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 构造法向量计算结果 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeCudaFree(d_normals); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_normals, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					               sampleCnt_v * sampleCnt_u * 3 * sizeof(float)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    size_t normalBytes = sampleCnt_u * sampleCnt_v * 3 * sizeof(float); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMalloc((void **) &d_normals, normalBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 构造线程层级 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    dim3 block(32, 32); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -437,13 +462,22 @@ __host__ void NurbsSurface::Surface::derivative(int sampleCnt_u, int sampleCnt_v | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        printf("GPU time cost of surface first derivative calculating for %d samples: %lf\n", sampleCnt_u * sampleCnt_v, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					               time_cost_device); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 结果数组 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_normals); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    h_normals = (float *) malloc(normalBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMemcpy(h_normals, d_normals, normalBytes, cudaMemcpyDeviceToHost); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_derivatives); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    h_derivatives = (float *) malloc(derBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMemcpy(h_derivatives, d_derivatives, derBytes, cudaMemcpyDeviceToHost); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaFree(d_derTexture_u); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaFree(d_derTexture_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void NurbsSurface::Surface::curvature(int sampleCnt_u, int sampleCnt_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 先计算切向量 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    derivative(sampleCnt_u, sampleCnt_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (POINT_SIZE != controlPoints[0][0].size()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        printf("Error! Nurbs控制点应表示为长度为4的齐次坐标\n"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -491,17 +525,18 @@ NurbsSurface::Surface::~Surface() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeCudaFree(d_normals); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeCudaFree(d_derivatives); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(bvh.nodes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_evaluations); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_normals); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(h_derivatives); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaDeviceReset(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void NurbsSurface::Surface::buildBHV(int layerCnt, bool useK) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void NurbsSurface::Surface::buildBVH(int layerCnt, bool useK) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // TODO 构造BVH的函数不应该出现在NURBS Surface中,应该是BVH类的事情! | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // TODO NURBS Surface只需要一个函数去调用BVH对象的方法即可 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    int sampleCnt_u = pow(2, layerCnt - 1) + 1, sampleCnt_v = sampleCnt_u; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (useK) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 先计算曲率,过程中也会计算曲面值 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        curvature(sampleCnt_u, sampleCnt_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 只做evaluation | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        evaluate(sampleCnt_u, sampleCnt_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (!useK) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 必须safeFree一下,这样global函数中才能通过d_k = nullptr知道不需要再free | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        safeCudaFree(d_k); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (POINT_SIZE != controlPoints[0][0].size()) { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -521,14 +556,15 @@ __host__ void NurbsSurface::Surface::buildBHV(int layerCnt, bool useK) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 记录用时 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    double time_cost_device; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (recordTime) time_cost_device = get_time(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    buildBvh<<<grid, block>>>(d_k, bvh.maxLevel, d_evaluationRes, knots_u[knots_u.size() - 1], | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                              knots_v[knots_v.size() - 1], sampleCnt_u, sampleCnt_v, d_bvh); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    g_buildBvh<<<grid, block>>>(d_k, bvh.maxLevel, d_evaluationRes, knots_u[knots_u.size() - 1], | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                knots_v[knots_v.size() - 1], sampleCnt_u, sampleCnt_v, d_bvh); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaDeviceSynchronize(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (recordTime) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        time_cost_device = get_time() - time_cost_device; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        printf("GPU time cost of a %d-layer BVH building: %lf\n", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					               bvh.maxLevel, time_cost_device); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 将bvh拷贝到cpu中 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    safeFree(bvh.nodes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bvh.nodes = (BVHNode *) malloc(bvhBytes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaMemcpy(bvh.nodes, d_bvh, bvhBytes, cudaMemcpyDeviceToHost); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -537,9 +573,9 @@ __host__ void NurbsSurface::Surface::buildBHV(int layerCnt, bool useK) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void NurbsSurface::Surface::buildGaussMap(int layerCnt) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // TODO,构造GAUSS Map的函数不应该出现在NURBS Surface中,应该是GAUSS Map类的事情! | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    int sampleCnt_u = pow(2, layerCnt - 1) + 1, sampleCnt_v = sampleCnt_u; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 先计算法向量 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    derivative(sampleCnt_u, sampleCnt_v); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (POINT_SIZE != controlPoints[0][0].size()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        printf("Error! Nurbs控制点应表示为长度为4的齐次坐标\n"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -556,8 +592,8 @@ __host__ void NurbsSurface::Surface::buildGaussMap(int layerCnt) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 记录用时 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    double time_cost_device; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (recordTime) time_cost_device = get_time(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    buildBvh<<<grid, block>>>(nullptr, layerCnt, d_normals, knots_u[knots_u.size() - 1], | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                              knots_v[knots_v.size() - 1], sampleCnt_u, sampleCnt_v, d_gaussMapTree); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    g_buildBvh<<<grid, block>>>(nullptr, layerCnt, d_normals, knots_u[knots_u.size() - 1], | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                knots_v[knots_v.size() - 1], sampleCnt_u, sampleCnt_v, d_gaussMapTree); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    cudaDeviceSynchronize(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (recordTime) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        time_cost_device = get_time() - time_cost_device; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -603,16 +639,24 @@ __host__ void NurbsSurface::recursiveGetOverlapLeafNodes(const BVH &bvh1, const | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ std::vector<std::pair<int, int>> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ std::vector<boxPair> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					NurbsSurface::getOverlappedLeafNodes(const BVH &bvh1, const BVH &bvh2) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<std::pair<int, int>> resPairs; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<idx2> resPairs; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 记录用时 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    double time_cost_device = get_time(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    recursiveGetOverlapLeafNodes(bvh1, bvh2, 0, 0, resPairs); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<boxPair> boxPairsIdx2(resPairs.size()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for (int i = 0; i < resPairs.size(); i++) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        boxPairsIdx2[i] = {{bvh1.nodes[resPairs[i].first].idx_u,  bvh1.nodes[resPairs[i].first].idx_v}, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                           {bvh2.nodes[resPairs[i].second].idx_u, bvh2.nodes[resPairs[i].second].idx_v}}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    time_cost_device = get_time() - time_cost_device; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    printf("CPU time cost for recursively calculating the overlapped leaf nodes: %lf\n", time_cost_device); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return resPairs; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return boxPairsIdx2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ bool | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -631,8 +675,10 @@ NurbsSurface::isGaussMapsOverlapped(const BVH &gm1, const BVH &gm2, std::pair<in | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        printf("Error when detecting overlapping: idx range invalid!\n"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto getRangedBox = [&commonMaxLayer](const BVH &bvh, const std::pair<int, int> &idxRange_u, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                          const std::pair<int, int> idxRange_v) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 获取某个范围的gauss map的aabb | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        AABB bounding; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (int i = idxRange_u.first; i <= idxRange_u.second; ++i) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for (int j = idxRange_v.first; j <= idxRange_v.second; ++j) { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -670,3 +716,69 @@ __host__ bool NurbsSurface::isGaussMapsOverlapped(const BVH &gm1, const BVH &gm2 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto idxRange_v2 = getIdxRange(range_v2, paramRange_v2, edgeCellCnt); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return isGaussMapsOverlapped(gm1, gm2, idxRange_u1, idxRange_v1, idxRange_u2, idxRange_v2); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ void | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					NurbsSurface::Surface::recursiveGetRayBVHIntersection(const glm::vec3 dir, const glm::vec3 startPoint, const int idx, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                      std::vector<BVHNode> &intersectionLeafNodes) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto bvhNode = bvh.nodes[idx]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 射线与AABB判交 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto isRayBoxIntersect = [&]() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const auto &box = bvhNode.bounds; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        float t; // 射线的参数,当t<=0,表示线面交点不在视平面前方,视为没有交点 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if (dir.x != 0.) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 当x分量不为0,则射线会与AABB中垂直于x轴的平面可能有交 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 注意x的正负。x为正会先遇到较小点所在平面 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (dir.x > 0) t = (box.pMin.x - startPoint.x) / dir.x; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else t = (box.pMax.x - startPoint.x) / dir.x; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (t > 0.) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // 射线与平面在前方有交点。但交点不一定在盒子上 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                auto tmpPt = startPoint + t * dir; // 交点 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (box.pMin.y <= tmpPt.y && box.pMin.z <= tmpPt.z && box.pMax.y >= tmpPt.y && box.pMax.z >= tmpPt.z) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if (dir.y != 0.) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 同上测试y方向 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (dir.y > 0) t = (box.pMin.y - startPoint.y) / dir.y; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else t = (box.pMax.y - startPoint.y) / dir.y; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (t > 0.) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                auto tmpPt = startPoint + t * dir; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (box.pMin.x <= tmpPt.x && box.pMin.z <= tmpPt.z && box.pMax.x >= tmpPt.x && box.pMax.z >= tmpPt.z) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if (dir.z != 0.) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // 同上测试z方向 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (dir.z > 0) t = (box.pMin.z - startPoint.z) / dir.z; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else t = (box.pMax.z - startPoint.z) / dir.z; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (t > 0.) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                auto tmpPt = startPoint + t * dir; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (box.pMin.x <= tmpPt.x && box.pMin.y <= tmpPt.y && box.pMax.x >= tmpPt.x && box.pMax.y >= tmpPt.y) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 不相交 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (!isRayBoxIntersect()) return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // 相交 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (bvhNode.firstChild == -1) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 与叶节点相交 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        intersectionLeafNodes.emplace_back(bvhNode); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // 与父节点相交 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (int i = 0; i < 4; i++) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            recursiveGetRayBVHIntersection(dir, startPoint, bvhNode.firstChild + i, intersectionLeafNodes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					__host__ std::vector<BVHNode> NurbsSurface::Surface::rayBVHIntersection(glm::vec3 dir, glm::vec3 startPoint) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<BVHNode> res; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    recursiveGetRayBVHIntersection(dir, startPoint, 0, res); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    //TODO sort res by t | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//    res.emplace_back(BVHNode()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//    printf("res size: %lld\n", res.size()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return res; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} |