bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const float *p1,const float *p2,const float *p3,float *sect) { float dir[3]; dir[0] = rayEnd[0] - rayStart[0]; dir[1] = rayEnd[1] - rayStart[1]; dir[2] = rayEnd[2] - rayStart[2]; float d = sqrtf(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]); float r = 1.0f / d; dir[0]*=r; dir[1]*=r; dir[2]*=r; float t; bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t ); if ( ret ) { if ( t > d ) { sect[0] = rayStart[0] + dir[0]*t; sect[1] = rayStart[1] + dir[1]*t; sect[2] = rayStart[2] + dir[2]*t; } else { ret = false; } } return ret; }
bool lineIntersectsTriangle(const double *rayStart,const double *rayEnd,const double *p1,const double *p2,const double *p3,double *sect) { double dir[3]; dir[0] = rayEnd[0] - rayStart[0]; dir[1] = rayEnd[1] - rayStart[1]; dir[2] = rayEnd[2] - rayStart[2]; double d = sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]); double r = 1.0f / d; dir[0]*=r; dir[1]*=r; dir[2]*=r; double t; bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t ); if ( ret ) { if ( t > d ) { sect[0] = rayStart[0] + dir[0]*t; sect[1] = rayStart[1] + dir[1]*t; sect[2] = rayStart[2] + dir[2]*t; } else { ret = false; } } return ret; }
// pocitanie funkcie pre vsetky trojuholniky, O(n2) void CSDFController::Compute(LinkedList<Face>* triangles, Octree* root) { float min = FLOAT_MAX; float max = 0.0; unsigned int n_rays = 30; float angle = 120.0f; unsigned int counter = 0; //------------------prealocated variables------------------ Vector4 tangens, normal, binormal; Mat4 t_mat; std::vector<float> rays; std::vector<float> weights; // precompute those N rays srand (123); // initial seed for random number generator float* rndy = new float[n_rays]; float* rndx = new float[n_rays]; for(unsigned int i = 0; i < n_rays; i++) { rndy[i] = float(rand()%int(angle / 2)); rndx[i] = float(rand()%(360)); if(rndy[i] == 0.0) rndy[i] = 0.5; } float dist = FLOAT_MAX; float dist2 = FLOAT_MAX; float theta = 0.0f; bool intersected = false; LinkedList<Face>* face_list = NULL; LinkedList<Face>::Cell<Face>* intersected_face = NULL; //------------------prealocated variables------------------ LinkedList<Face>::Cell<Face>* current_face = triangles->start; while(current_face != NULL) { // vypocet TNB vektorov a matice ComputeTNB(current_face->data, tangens, normal, binormal); t_mat = Mat4(tangens, normal, binormal); rays.clear(); weights.clear(); for(unsigned int i = 0; i < n_rays; i++) { Vector4 ray = CalcRayFromAngle(rndx[i], rndy[i]) * t_mat; ray.Normalize(); dist = FLOAT_MAX; face_list = GetFaceList(triangles, root, current_face->data->center, ray); intersected_face = face_list->start; while(intersected_face != NULL) { if(current_face == intersected_face) { intersected_face = intersected_face->next; continue; } dist2 = FLOAT_MAX; intersected = rayIntersectsTriangle(current_face->data->center, ray, intersected_face->data->v[0]->P, intersected_face->data->v[1]->P, intersected_face->data->v[2]->P, dist2); if(intersected == true) { theta = acos( (ray * intersected_face->data->normal) / (ray.Length() * intersected_face->data->normal.Length()) ); theta = theta * float(180.0 / M_PI); //loggger->logInfo(MarshalString("pridany ray s thetou: " + theta)); if((theta < 90.0f) && (dist2 < dist)) dist = dist2; } intersected_face = intersected_face->next; } if(dist < (FLOAT_MAX - 1.0f)) { //loggger->logInfo(MarshalString("pridany ray s dlzkou: " + dist)); rays.push_back(dist); weights.push_back(180.0f - rndy[i]); } //if(root != NULL) //delete face_list; // generated list, bez prealokovania } if(rays.size() > 0) { current_face->data->ComputeSDFValue(rays, weights); if(current_face->data->diameter->value < min) min = current_face->data->diameter->value; if(current_face->data->diameter->value > max) max = current_face->data->diameter->value; } counter = counter + 1; current_face = current_face->next; } fc_list->Clear(); oc_list->Clear(); delete [] rndy; delete [] rndx; // postprocessing - smoothing and normalization //float kernel[] = {1.0,4.0,6.0,4.0,1.0}; float* kernel = ComputeGaussianKernel(kernel_size); current_face = triangles->start; while(current_face != NULL) { Smooth(current_face->data, kernel, kernel_size); current_face->data->diameter->Normalize1(min, max, 4.0); current_face->data->diameter->Normalize2(0, max, 4.0); //tmp->data->diameter->Normalize2(0, diagonal, 4.0); current_face = current_face->next; } delete kernel; }
virtual bool raycast(const double *from, // The starting point of the raycast const double *to, // The ending point of the raycast const double *closestToPoint, // The point to match the nearest hit location (can just be the 'from' location of no specific point) double *hitLocation, // The point where the ray hit nearest to the 'closestToPoint' location double *hitDistance) final // The distance the ray traveled to the hit location { bool ret = false; double dir[3]; dir[0] = to[0] - from[0]; dir[1] = to[1] - from[1]; dir[2] = to[2] - from[2]; double distance = sqrt( dir[0]*dir[0] + dir[1]*dir[1]+dir[2]*dir[2] ); if ( distance < 0.0000000001f ) return false; double recipDistance = 1.0f / distance; dir[0]*=recipDistance; dir[1]*=recipDistance; dir[2]*=recipDistance; const uint32_t *indices = mIndices; const double *vertices = mVertices; double nearestDistance = distance; for (uint32_t tri=0; tri<mTcount; tri++) { uint32_t i1 = indices[tri*3+0]; uint32_t i2 = indices[tri*3+1]; uint32_t i3 = indices[tri*3+2]; const double *p1 = &vertices[i1*3]; const double *p2 = &vertices[i2*3]; const double *p3 = &vertices[i3*3]; double t; if ( rayIntersectsTriangle(from,dir,p1,p2,p3,t)) { double hitPos[3]; hitPos[0] = from[0] + dir[0] * t; hitPos[1] = from[1] + dir[1] * t; hitPos[2] = from[2] + dir[2] * t; double pointDistance = getPointDistance(hitPos, closestToPoint); if (pointDistance < nearestDistance ) { nearestDistance = pointDistance; if ( hitLocation ) { hitLocation[0] = hitPos[0]; hitLocation[1] = hitPos[1]; hitLocation[2] = hitPos[2]; } if ( hitDistance ) { *hitDistance = pointDistance; } ret = true; } } } return ret; }
virtual void raycast(bool &hit, const float *from, const float *dir, float *hitLocation, float *hitNormal, float *hitDistance, const float *vertices, const uint32 *indices, float &nearestDistance, NodeInterface *callback, unsigned char *raycastTriangles, unsigned char raycastFrame, const TriVector &leafTriangles) { float sect[3]; float nd = nearestDistance; if ( !intersectLineSegmentAABB(mBounds.mMin,mBounds.mMax,from,dir,nd,sect) ) { return; } if ( mLeafTriangleIndex != TRI_EOF ) { const uint32 *scan = &leafTriangles[mLeafTriangleIndex]; uint32 count = *scan++; for (uint32 i=0; i<count; i++) { uint32 tri = *scan++; if ( raycastTriangles[tri] != raycastFrame ) { raycastTriangles[tri] = raycastFrame; uint32 i1 = indices[tri*3+0]; uint32 i2 = indices[tri*3+1]; uint32 i3 = indices[tri*3+2]; const float *p1 = &vertices[i1*3]; const float *p2 = &vertices[i2*3]; const float *p3 = &vertices[i3*3]; float t; if ( rayIntersectsTriangle(from,dir,p1,p2,p3,t)) { if ( t < nearestDistance ) { nearestDistance = t; if ( hitLocation ) { hitLocation[0] = from[0]+dir[0]*t; hitLocation[1] = from[1]+dir[1]*t; hitLocation[2] = from[2]+dir[2]*t; } if ( hitNormal ) { callback->getFaceNormal(tri,hitNormal); } if ( hitDistance ) { *hitDistance = t; } hit = true; } } } } } else { if ( mLeft ) { mLeft->raycast(hit,from,dir,hitLocation,hitNormal,hitDistance,vertices,indices,nearestDistance,callback,raycastTriangles,raycastFrame,leafTriangles); } if ( mRight ) { mRight->raycast(hit,from,dir,hitLocation,hitNormal,hitDistance,vertices,indices,nearestDistance,callback,raycastTriangles,raycastFrame,leafTriangles); } } }