/// checks if a ray intersects the mesh, ray_origin and ray_dir must be in local coordinates /// returns face index that was hit, or -1 if nothing hit int MeshShape::RayIntersect (const Vector3& ray_origin,const Vector3& ray_dir,float* pfHitDist) { if (mpMesh.isNull()) return -1; // check bounding sphere first //printf("#WWW### MeshShape::RayIntersect %f\n",mpMesh->getBoundingSphereRadius()); Vector3 vMid = 0.5*(mvMin + mvMax); float fRad = mymax((mvMin-vMid).length(),(mvMax-vMid).length()); //float fRad = mpMesh->getBoundingSphereRadius(); if (!Ogre::Ray(ray_origin,ray_dir).intersects(Ogre::Sphere(vMid,fRad + 0.1)).first) return -1; //printf("MeshShape::RayIntersect hitbounds : rad=%f\n",fRad); int iFaceHit = -1; float myHitDist; //printf("#WWW### MeshShape::RayIntersect rayhit %d\n",mlIndices.size()); for (int i=0;i<mlIndices.size();i+=3) { if (IntersectRayTriangle(ray_origin,ray_dir, mlVertices[mlIndices[i+0]], mlVertices[mlIndices[i+1]], mlVertices[mlIndices[i+2]],&myHitDist)) { if (iFaceHit == -1 || myHitDist < *pfHitDist) { *pfHitDist = myHitDist; iFaceHit = i/3; } } } //printf("MeshShape::RayIntersect hit=%d dist=%f\n",bHit?1:0,bHit?(*pfHitDist):0); return iFaceHit; }
void MeshShape::RayIntersect (const Ogre::Vector3& ray_origin,const Ogre::Vector3& ray_dir,std::vector<std::pair<float,int> > &pHitList) { if (mpMesh.isNull()) return; Vector3 vMid = 0.5*(mvMin + mvMax); float fRad = mymax((mvMin-vMid).length(),(mvMax-vMid).length()); if (!Ogre::Ray(ray_origin,ray_dir).intersects(Ogre::Sphere(vMid,fRad + 0.1)).first) return; float myHitDist; for (int i=0;i<mlIndices.size();i+=3) { if (IntersectRayTriangle(ray_origin,ray_dir, mlVertices[mlIndices[i+0]], mlVertices[mlIndices[i+1]], mlVertices[mlIndices[i+2]],&myHitDist)) { pHitList.push_back(std::make_pair(myHitDist,i/3)); } } }
DWORD MeshParameterization::OnIntersectRayTriangle( DWORD size, void * params ) { VERIFY_MESSAGE_SIZE( size, sizeof( MESHPARAMINTERSECTRAYTRIANGLEMSG ) ); MESHPARAMINTERSECTRAYTRIANGLEMSG * msg = (MESHPARAMINTERSECTRAYTRIANGLEMSG*)params; if( msg != NULL ) { if( msg->inRay != NULL ) { Ray inRay = *msg->inRay; msg->outCollided = IntersectRayTriangle( inRay, msg->outFaceIndex, &msg->outIntersectionDistance, &msg->outULength, &msg->outVLength ); return MSG_HANDLED_STOP; } } return MSG_ERROR; }
bool RMNode::Raycast(const Vec3<Float> & from, const Vec3<Float> & dir, long & triID, Float & distance, Vec3<Real> & hitPoint, Vec3<Real> & hitNormal) const { Float distToSphere; if (m_bBox.Raycast(from, dir, distToSphere) && (distToSphere < distance)) { if (m_leaf) { long f, i1, j1, k1; Vec3<long> * const triangles = m_rm->m_triangles; Vec3<Float> * const vertices = m_rm->m_vertices; Vec3<Real> u1, v1, normal1; double dist = 0.0; long nhit = 0; bool ret = false; for(size_t id = 0; id < m_triIDs.Size(); ++id) { f = m_triIDs[id]; i1 = triangles[f].X(); j1 = triangles[f].Y(); k1 = triangles[f].Z(); u1 = vertices[j1] - vertices[i1]; v1 = vertices[k1] - vertices[i1]; normal1 = (u1 ^ v1); if (dir * normal1 > 0.0) { nhit = IntersectRayTriangle(from, dir, vertices[i1], vertices[j1], vertices[k1], dist); if (nhit==1 && distance>dist) { normal1.Normalize(); hitNormal = normal1; hitPoint = from + dist * dir; distance = dist; triID = f; ret = true; } } } return ret; } bool ret1 = false; bool ret2 = false; if (m_idRight >= 0) ret1 = m_rm->m_nodes[m_idRight].Raycast(from, dir, triID, distance, hitPoint, hitNormal); if (m_idLeft >= 0) ret2 = m_rm->m_nodes[m_idLeft].Raycast(from, dir, triID, distance, hitPoint, hitNormal); return ret1 || ret2; } return false; }
bool CCoherentGeometry::IntersectWithRay( const Vec3& rayOriginModelSpace, const Vec3& rayDirectionModelSpace, float& outDist, float& outU, float& outV ) { static const int NO_HIT = -1; int hitFaceIndex = NO_HIT; // Actually index of the hit face's first vertex index in the indices array, but never mind float minDist = std::numeric_limits<float>::max(); float texU = 0; float texV = 0; for ( size_t i = 0; i < m_Vertices.size(); i += 3 ) { float t, u, v; const Vec3& v0 = m_Vertices[i]; const Vec3& v1 = m_Vertices[i + 1]; const Vec3& v2 = m_Vertices[i + 2]; if ( IntersectRayTriangle( rayOriginModelSpace, rayDirectionModelSpace, v0, v1, v2, t, u, v ) ) { if ( t < minDist ) { minDist = t; // Temporarily save barycentric coordinates here texU = u; texV = v; hitFaceIndex = i; } } } if ( hitFaceIndex != NO_HIT ) { // Compute texture coordinates from barycentric coordinates Vec2 texCoords = ( 1 - texU - texV ) * m_TexCoords[hitFaceIndex] + texU * m_TexCoords[hitFaceIndex + 1] + texV * m_TexCoords[hitFaceIndex + 2]; outU = texCoords.x; outV = 1.0f - texCoords.y; outDist = minDist; return true; } return false; }
int IntersectSegmentTriangle(const vec3d& s0, const vec3d& s1, const vec3d p[3], double& t, vec3d& uvw, vec3d& xyz) { vec3d delta = s1 - s0; vec3d rd = delta.normalized(); double deltaLen = delta.length(); vec3d uvt; int res = IntersectRayTriangle(s0, rd, p, uvt); if(res > 0) { if(uvt.z >= 0.0 && uvt.z <= deltaLen) { //Barycentric coordinate uvw = vec3d(uvt.x, uvt.y, 1.0 - uvt.x - uvt.y); //Cartesian Coordinate xyz = s0 + rd * uvt.z; //return the t distance on the segment t = uvt.z; return res; } } return 0; }
void HACD::InitializeDualGraph() { long i, j, k; Vec3<Real> u, v, w, normal; delete [] m_normals; m_normals = new Vec3<Real>[m_nPoints]; if (m_addFacesPoints) { delete [] m_facePoints; delete [] m_faceNormals; m_facePoints = new Vec3<Real>[m_nTriangles]; m_faceNormals = new Vec3<Real>[m_nTriangles]; } memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints); for(unsigned long f = 0; f < m_nTriangles; f++) { if (m_callBack) (*m_callBack)("+ InitializeDualGraph\n", f, m_nTriangles, 0); if (gCancelRequest) return; i = m_triangles[f].X(); j = m_triangles[f].Y(); k = m_triangles[f].Z(); m_graph.m_vertices[f].m_distPoints[i].m_distOnly = false; m_graph.m_vertices[f].m_distPoints[j].m_distOnly = false; m_graph.m_vertices[f].m_distPoints[k].m_distOnly = false; ICHull * ch = new ICHull; m_graph.m_vertices[f].m_convexHull = ch; ch->AddPoint(m_points[i], i); ch->AddPoint(m_points[j], j); ch->AddPoint(m_points[k], k); ch->SetDistPoints(&m_graph.m_vertices[f].m_distPoints); u = m_points[j] - m_points[i]; v = m_points[k] - m_points[i]; w = m_points[k] - m_points[j]; normal = u ^ v; m_normals[i] += normal; m_normals[j] += normal; m_normals[k] += normal; m_graph.m_vertices[f].m_surf = normal.GetNorm(); m_graph.m_vertices[f].m_perimeter = u.GetNorm() + v.GetNorm() + w.GetNorm(); normal.Normalize(); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(i,j)); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(j,k)); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(k,i)); if(m_addFacesPoints) { m_faceNormals[f] = normal; m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0; m_graph.m_vertices[f].m_distPoints[-static_cast<long>(f)-1].m_distOnly = true; } if (m_addExtraDistPoints) {// we need a kd-tree structure to accelerate this part! long i1, j1, k1; Vec3<Real> u1, v1, normal1; normal = -normal; double distance = 0.0; double distMin = 0.0; size_t faceIndex = m_nTriangles; Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0); long nhit = 0; for(size_t f1 = 0; f1 < m_nTriangles; f1++) { i1 = m_triangles[f1].X(); j1 = m_triangles[f1].Y(); k1 = m_triangles[f1].Z(); u1 = m_points[j1] - m_points[i1]; v1 = m_points[k1] - m_points[i1]; normal1 = (u1 ^ v1); if (normal * normal1 > 0.0) { nhit = IntersectRayTriangle(Vec3<double>(seedPoint.X(), seedPoint.Y(), seedPoint.Z()), Vec3<double>(normal.X(), normal.Y(), normal.Z()), Vec3<double>(m_points[i1].X(), m_points[i1].Y(), m_points[i1].Z()), Vec3<double>(m_points[j1].X(), m_points[j1].Y(), m_points[j1].Z()), Vec3<double>(m_points[k1].X(), m_points[k1].Y(), m_points[k1].Z()), distance); if ((nhit==1) && ((distMin > distance) || (faceIndex == m_nTriangles))) { distMin = distance; faceIndex = f1; } } } if (faceIndex < m_nTriangles ) { i1 = m_triangles[faceIndex].X(); j1 = m_triangles[faceIndex].Y(); k1 = m_triangles[faceIndex].Z(); m_graph.m_vertices[f].m_distPoints[i1].m_distOnly = true; m_graph.m_vertices[f].m_distPoints[j1].m_distOnly = true; m_graph.m_vertices[f].m_distPoints[k1].m_distOnly = true; if (m_addFacesPoints) { m_graph.m_vertices[f].m_distPoints[-static_cast<long>(faceIndex)-1].m_distOnly = true; } } } } for (size_t v = 0; v < m_nPoints; v++) { m_normals[v].Normalize(); } }
double ICHull::ComputeDistance(long name, const Vec3<Real> & pt, const Vec3<Real> & normal, bool & insideHull, bool updateIncidentPoints) { if (m_isFlat) { return 0.0; } else { Vec3<double> p0( static_cast<double>(pt.X()), static_cast<double>(pt.Y()), static_cast<double>(pt.Z())); Vec3<double> ptNormal(static_cast<double>(normal.X()), static_cast<double>(normal.Y()), static_cast<double>(normal.Z())); Vec3<double> impact; long nhit; double dist; double distance = 0.0; size_t nT = m_mesh.GetNTriangles(); insideHull = false; CircularListElement<TMMTriangle> * face = 0; Vec3<double> ver0, ver1, ver2; for(size_t f = 0; f < nT; f++) { TMMTriangle & currentTriangle = m_mesh.m_triangles.GetHead()->GetData(); nhit = 0; if (currentTriangle.m_vertices[0]->GetData().m_name != currentTriangle.m_vertices[1]->GetData().m_name && currentTriangle.m_vertices[1]->GetData().m_name != currentTriangle.m_vertices[2]->GetData().m_name && currentTriangle.m_vertices[2]->GetData().m_name != currentTriangle.m_vertices[0]->GetData().m_name) { if (currentTriangle.m_vertices[0]->GetData().m_name == name || currentTriangle.m_vertices[1]->GetData().m_name == name || currentTriangle.m_vertices[2]->GetData().m_name == name) { nhit = 1; dist = 0.0; } else { ver0.X() = currentTriangle.m_vertices[0]->GetData().m_pos.X(); ver0.Y() = currentTriangle.m_vertices[0]->GetData().m_pos.Y(); ver0.Z() = currentTriangle.m_vertices[0]->GetData().m_pos.Z(); ver1.X() = currentTriangle.m_vertices[1]->GetData().m_pos.X(); ver1.Y() = currentTriangle.m_vertices[1]->GetData().m_pos.Y(); ver1.Z() = currentTriangle.m_vertices[1]->GetData().m_pos.Z(); ver2.X() = currentTriangle.m_vertices[2]->GetData().m_pos.X(); ver2.Y() = currentTriangle.m_vertices[2]->GetData().m_pos.Y(); ver2.Z() = currentTriangle.m_vertices[2]->GetData().m_pos.Z(); Vec3<Real> faceNormal = (ver1-ver0) ^ (ver2-ver0); faceNormal.Normalize(); if (ptNormal*normal > 0.0) { nhit = IntersectRayTriangle(p0, ptNormal, ver0, ver1, ver2, dist); } } #ifdef HACD_DEBUG std::cout << "T " << currentTriangle.m_vertices[0]->GetData().m_name << " " << currentTriangle.m_vertices[1]->GetData().m_name << " " << currentTriangle.m_vertices[2]->GetData().m_name << " " << nhit << " " << dist << std::endl; #endif if (nhit == 1 && (!insideHull || dist > distance) ) { distance = dist; insideHull = true; face = m_mesh.m_triangles.GetHead(); } } m_mesh.m_triangles.Next(); } if (updateIncidentPoints && face && m_distPoints) { (*m_distPoints)[name].m_dist = static_cast<Real>(distance); face->GetData().m_incidentPoints.Insert(name); } return distance; } }