Vector3 Mesh::faceNormal(const Point3 &p0, const Point3 &p1, const Point3 &p2) { // // ASSIGNMENT (PA04) // // The points p0, p1, and p2 bound a triangular face in clockwise // order. Compute two edges, take their cross product, and // normalize the result to get the face normal, which you return. // // 8 lines in instructor solution (YMMV) // // Get two edges (DOUBLE CHECK THIS) double e0x = p2.u.g.x - p1.u.g.x; double e0y = p2.u.g.y - p1.u.g.y; double e0z = p2.u.g.z - p1.u.g.z; double e1x = p1.u.g.x - p0.u.g.x; double e1y = p1.u.g.y - p0.u.g.y; double e1z = p1.u.g.z - p0.u.g.z; Vector3 edge0(e0x, e0y, e0z); Vector3 edge1(e1x, e1y, e1z); // Compute their cross product Vector3 cross = edge1.cross(edge0); // Find the normal //double magnitude = cross.mag(); //Vector3 normal = cross / magnitude; return cross.normalized(); // permits template to compile cleanly }
double SurfaceOverlapFacet::projected_overlap( SurfaceOverlapFacet &other_facet, CubitBoolean draw_overlap ) { double tmp_double = agt->ProjectedOverlap( t, other_facet.t, draw_overlap ); if( tmp_double > 0.00 ) { CubitVector edge0(t.e0.x, t.e0.y, t.e0.z); CubitVector edge1(t.e1.x, t.e1.y, t.e1.z); CubitVector normal = edge0 * edge1; double area_facet1 = normal.length() / 2; edge0.set(other_facet.t.e0.x, other_facet.t.e0.y, other_facet.t.e0.z); edge1.set(other_facet.t.e1.x, other_facet.t.e1.y, other_facet.t.e1.z); normal = edge0 * edge1; double area_facet2 = normal.length() / 2; //don't report overlapping area between facets unless it is greater //than one hundredth of the area of the smaller facet if( area_facet1 < area_facet2 ) { if( tmp_double < (area_facet1*0.01)) tmp_double = 0.0; } else if( tmp_double < (area_facet2*0.01 )) tmp_double = 0.0; } return tmp_double; }
Vector3 Mesh::faceNormal(const Point3 &p0, const Point3 &p1, const Point3 &p2) { // // Copy your previous (PA04) solution here. // // Get two edges (DOUBLE CHECK THIS) double e0x = p2.u.g.x - p1.u.g.x; double e0y = p2.u.g.y - p1.u.g.y; double e0z = p2.u.g.z - p1.u.g.z; double e1x = p1.u.g.x - p0.u.g.x; double e1y = p1.u.g.y - p0.u.g.y; double e1z = p1.u.g.z - p0.u.g.z; Vector3 edge0(e0x, e0y, e0z); Vector3 edge1(e1x, e1y, e1z); // Compute their cross product Vector3 cross = edge1.cross(edge0); // Find the normal //double magnitude = cross.mag(); //Vector3 normal = cross / magnitude; return cross.normalized(); // permits template to compile cleanly }
Foam::label Foam::removePoints::countPointUsage ( const scalar minCos, boolList& pointCanBeDeleted ) const { // Containers to store two edges per point: // -1 : not filled // >= 0 : edge label // -2 : more than two edges for point labelList edge0(mesh_.nPoints(), -1); labelList edge1(mesh_.nPoints(), -1); const edgeList& edges = mesh_.edges(); forAll(edges, edgeI) { const edge& e = edges[edgeI]; forAll(e, eI) { label pointI = e[eI]; if (edge0[pointI] == -2) { // Already too many edges } else if (edge0[pointI] == -1) { // Store first edge using point edge0[pointI] = edgeI; } else { // Already one edge using point. Check second container. if (edge1[pointI] == -1) { // Store second edge using point edge1[pointI] = edgeI; } else { // Third edge using point. Mark. edge0[pointI] = -2; edge1[pointI] = -2; } } } }
bool BSPTree::intersect(Ray &ray, const ISectTri &isecttri, double t_max) const { tri_calls++; // This is the Möller-Trumbore method Vec3d direction(ray.direction); Vec3d edge0(isecttri.edge0); Vec3d edge1(isecttri.edge1); // Ray-triangle intersection Vec3d p = cross(direction, edge1); double a = dot(edge0, p); if(a > -d_eps && a < d_eps) return false; // Just delay these Vec3d origin(ray.origin); Vec3d point0(isecttri.point0); double f = 1.0/a; Vec3d s = origin - point0; double u = f*dot(s, p); if(u < 0.0 || u > 1.0) return false; Vec3d q = cross(s, edge0); double v = f*dot(direction, q); if(v < 0.0 || u + v > 1.0) return false; double t = f*dot(edge1, q); if(t < f_eps || t*t < 1.0e-9) return false; if(t > t_max) return false; if(t > ray.dist) return false; ray.dist = t; ray.u = u; ray.v = v; ray.hit_object = (TriMesh*)isecttri.mesh_id; ray.hit_face_id = isecttri.tri_id; ray.has_hit=true; return true; }
dgFloat32 dgFastRayTest::PolygonIntersect (const dgVector& faceNormal, dgFloat32 maxT, const dgFloat32* const polygon, dgInt32 strideInBytes, const dgInt32* const indexArray, dgInt32 indexCount) const { dgAssert (m_p0.m_w == dgFloat32 (0.0f)); dgAssert (m_p1.m_w == dgFloat32 (0.0f)); if (faceNormal.DotProduct(m_unitDir).GetScalar() < dgFloat32 (0.0f)) { dgInt32 stride = dgInt32(strideInBytes / sizeof (dgFloat32)); dgBigVector v0(dgVector(&polygon[indexArray[indexCount - 1] * stride]) & dgVector::m_triplexMask); dgBigVector p0(m_p0); dgBigVector p0v0(v0 - p0); dgBigVector diff(m_diff); dgBigVector normal(faceNormal); dgFloat64 tOut = normal.DotProduct(p0v0).GetScalar() / normal.DotProduct(diff).GetScalar(); if ((tOut >= dgFloat64(0.0f)) && (tOut <= maxT)) { dgBigVector p (p0 + diff.Scale (tOut)); dgBigVector unitDir(m_unitDir); for (dgInt32 i = 0; i < indexCount; i++) { dgInt32 i2 = indexArray[i] * stride; dgBigVector v1(dgVector(&polygon[i2]) & dgVector::m_triplexMask); dgBigVector edge0(p - v0); dgBigVector edge1(v1 - v0); dgFloat64 area = unitDir.DotProduct (edge0.CrossProduct(edge1)).GetScalar(); if (area < dgFloat32 (0.0f)) { return 1.2f; } v0 = v1; } return dgFloat32(tOut); } } return dgFloat32 (1.2f); }
hacd::HaI32 dgPolygonSoupDatabaseBuilder::FilterFace (hacd::HaI32 count, hacd::HaI32* const pool) { if (count == 3) { dgBigVector p0 (m_vertexPoints[pool[2]]); for (hacd::HaI32 i = 0; i < 3; i ++) { dgBigVector p1 (m_vertexPoints[pool[i]]); dgBigVector edge (p1 - p0); hacd::HaF64 mag2 = edge % edge; if (mag2 < hacd::HaF32 (1.0e-6f)) { count = 0; } p0 = p1; } if (count == 3) { dgBigVector edge0 (m_vertexPoints[pool[2]] - m_vertexPoints[pool[0]]); dgBigVector edge1 (m_vertexPoints[pool[1]] - m_vertexPoints[pool[0]]); dgBigVector normal (edge0 * edge1); hacd::HaF64 mag2 = normal % normal; if (mag2 < hacd::HaF32 (1.0e-8f)) { count = 0; } } } else { dgPolySoupFilterAllocator polyhedra; count = polyhedra.AddFilterFace (hacd::HaU32 (count), pool); if (!count) { return 0; } dgEdge* edge = &polyhedra.GetRoot()->GetInfo(); if (edge->m_incidentFace < 0) { edge = edge->m_twin; } bool flag = true; while (flag) { flag = false; if (count >= 3) { dgEdge* ptr = edge; dgBigVector p0 (&m_vertexPoints[ptr->m_incidentVertex].m_x); do { dgBigVector p1 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x); dgBigVector e0 (p1 - p0); hacd::HaF64 mag2 = e0 % e0; if (mag2 < hacd::HaF32 (1.0e-6f)) { count --; flag = true; edge = ptr->m_next; ptr->m_prev->m_next = ptr->m_next; ptr->m_next->m_prev = ptr->m_prev; ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev; ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next; break; } p0 = p1; ptr = ptr->m_next; } while (ptr != edge); } } if (count >= 3) { flag = true; dgBigVector normal (polyhedra.FaceNormal (edge, &m_vertexPoints[0].m_x, sizeof (dgBigVector))); HACD_ASSERT ((normal % normal) > hacd::HaF32 (1.0e-10f)); normal = normal.Scale (dgRsqrt (normal % normal + hacd::HaF32 (1.0e-20f))); while (flag) { flag = false; if (count >= 3) { dgEdge* ptr = edge; dgBigVector p0 (&m_vertexPoints[ptr->m_prev->m_incidentVertex].m_x); dgBigVector p1 (&m_vertexPoints[ptr->m_incidentVertex].m_x); dgBigVector e0 (p1 - p0); e0 = e0.Scale (dgRsqrt (e0 % e0 + hacd::HaF32(1.0e-10f))); do { dgBigVector p2 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x); dgBigVector e1 (p2 - p1); e1 = e1.Scale (dgRsqrt (e1 % e1 + hacd::HaF32(1.0e-10f))); hacd::HaF64 mag2 = e1 % e0; if (mag2 > hacd::HaF32 (0.9999f)) { count --; flag = true; edge = ptr->m_next; ptr->m_prev->m_next = ptr->m_next; ptr->m_next->m_prev = ptr->m_prev; ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev; ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next; break; } dgBigVector n (e0 * e1); mag2 = n % normal; if (mag2 < hacd::HaF32 (1.0e-5f)) { count --; flag = true; edge = ptr->m_next; ptr->m_prev->m_next = ptr->m_next; ptr->m_next->m_prev = ptr->m_prev; ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev; ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next; break; } e0 = e1; p1 = p2; ptr = ptr->m_next; } while (ptr != edge); } } } dgEdge* first = edge; if (count >= 3) { hacd::HaF64 best = hacd::HaF32 (2.0f); dgEdge* ptr = edge; dgBigVector p0 (&m_vertexPoints[ptr->m_incidentVertex].m_x); dgBigVector p1 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x); dgBigVector e0 (p1 - p0); e0 = e0.Scale (dgRsqrt (e0 % e0 + hacd::HaF32(1.0e-10f))); do { dgBigVector p2 (&m_vertexPoints[ptr->m_next->m_next->m_incidentVertex].m_x); dgBigVector e1 (p2 - p1); e1 = e1.Scale (dgRsqrt (e1 % e1 + hacd::HaF32(1.0e-10f))); hacd::HaF64 mag2 = fabs (e1 % e0); if (mag2 < best) { best = mag2; first = ptr; } e0 = e1; p1 = p2; ptr = ptr->m_next; } while (ptr != edge); count = 0; ptr = first; do { pool[count] = ptr->m_incidentVertex; count ++; ptr = ptr->m_next; } while (ptr != first); } #ifdef _DEBUG if (count >= 3) { hacd::HaI32 j0 = count - 2; hacd::HaI32 j1 = count - 1; dgBigVector normal (polyhedra.FaceNormal (edge, &m_vertexPoints[0].m_x, sizeof (dgBigVector))); for (hacd::HaI32 j2 = 0; j2 < count; j2 ++) { dgBigVector p0 (&m_vertexPoints[pool[j0]].m_x); dgBigVector p1 (&m_vertexPoints[pool[j1]].m_x); dgBigVector p2 (&m_vertexPoints[pool[j2]].m_x); dgBigVector e0 ((p0 - p1)); dgBigVector e1 ((p2 - p1)); dgBigVector n (e1 * e0); HACD_ASSERT ((n % normal) > hacd::HaF32 (0.0f)); j0 = j1; j1 = j2; } } #endif } return (count >= 3) ? count : 0; }
void dgPolygonSoupDatabaseBuilder::AddMesh (const hacd::HaF32* const vertex, hacd::HaI32 vertexCount, hacd::HaI32 strideInBytes, hacd::HaI32 faceCount, const hacd::HaI32* const faceArray, const hacd::HaI32* const indexArray, const hacd::HaI32* const faceTagsData, const dgMatrix& worldMatrix) { hacd::HaI32 faces[256]; hacd::HaI32 pool[2048]; m_vertexPoints[m_vertexCount + vertexCount].m_x = hacd::HaF64 (0.0f); dgBigVector* const vertexPool = &m_vertexPoints[m_vertexCount]; worldMatrix.TransformTriplex (&vertexPool[0].m_x, sizeof (dgBigVector), vertex, strideInBytes, vertexCount); for (hacd::HaI32 i = 0; i < vertexCount; i ++) { vertexPool[i].m_w = hacd::HaF64 (0.0f); } hacd::HaI32 totalIndexCount = faceCount; for (hacd::HaI32 i = 0; i < faceCount; i ++) { totalIndexCount += faceArray[i]; } m_vertexIndex[m_indexCount + totalIndexCount] = 0; m_faceVertexCount[m_faceCount + faceCount] = 0; hacd::HaI32 k = 0; for (hacd::HaI32 i = 0; i < faceCount; i ++) { hacd::HaI32 count = faceArray[i]; for (hacd::HaI32 j = 0; j < count; j ++) { hacd::HaI32 index = indexArray[k]; pool[j] = index + m_vertexCount; k ++; } hacd::HaI32 convexFaces = 0; if (count == 3) { convexFaces = 1; dgBigVector p0 (m_vertexPoints[pool[2]]); for (hacd::HaI32 i = 0; i < 3; i ++) { dgBigVector p1 (m_vertexPoints[pool[i]]); dgBigVector edge (p1 - p0); hacd::HaF64 mag2 = edge % edge; if (mag2 < hacd::HaF32 (1.0e-6f)) { convexFaces = 0; } p0 = p1; } if (convexFaces) { dgBigVector edge0 (m_vertexPoints[pool[2]] - m_vertexPoints[pool[0]]); dgBigVector edge1 (m_vertexPoints[pool[1]] - m_vertexPoints[pool[0]]); dgBigVector normal (edge0 * edge1); hacd::HaF64 mag2 = normal % normal; if (mag2 < hacd::HaF32 (1.0e-8f)) { convexFaces = 0; } } if (convexFaces) { faces[0] = 3; } } else { convexFaces = AddConvexFace (count, pool, faces); } hacd::HaI32 index = 0; for (hacd::HaI32 k = 0; k < convexFaces; k ++) { hacd::HaI32 count = faces[k]; m_vertexIndex[m_indexCount] = faceTagsData[i]; m_indexCount ++; for (hacd::HaI32 j = 0; j < count; j ++) { m_vertexIndex[m_indexCount] = pool[index]; index ++; m_indexCount ++; } m_faceVertexCount[m_faceCount] = count + 1; m_faceCount ++; } } m_vertexCount += vertexCount; m_run -= vertexCount; if (m_run <= 0) { PackArray(); } }
HE_Mesh::HE_Mesh(FVMesh& mesh) : Mesh(nullptr) { for (int vIdx = 0 ; vIdx < mesh.vertices.size() ; vIdx++) { vertices.push_back(HE_Vertex(mesh.vertices[vIdx].p, -1)); } for (int fIdx = 0 ; fIdx < mesh.faces.size() ; fIdx++) { FVMeshFace& fvFace = mesh.faces[fIdx]; HE_Face heFace; HE_Edge edge0(fvFace.vertex_index[0], fIdx); // vertices in face are ordered counter-clockwise HE_Edge edge1(fvFace.vertex_index[1], fIdx); HE_Edge edge2(fvFace.vertex_index[2], fIdx); int newEdgeIndex = edges.size(); vertices[ fvFace.vertex_index[0] ].someEdge_idx = newEdgeIndex+0; // overwrites existing data, if present vertices[ fvFace.vertex_index[1] ].someEdge_idx = newEdgeIndex+1; vertices[ fvFace.vertex_index[2] ].someEdge_idx = newEdgeIndex+2; edge0.next_edge_idx = newEdgeIndex+1; edge1.next_edge_idx = newEdgeIndex+2; edge2.next_edge_idx = newEdgeIndex+0; edges.push_back(edge0); edges.push_back(edge1); edges.push_back(edge2); heFace.edge_idx[0] = newEdgeIndex+0; heFace.edge_idx[1] = newEdgeIndex+1; heFace.edge_idx[2] = newEdgeIndex+2; faces.push_back(heFace); } // connect half-edges: bool faceEdgeIsConnected[mesh.faces.size()][3] = {}; // initialize all as false // for each edge of each face : if it doesn't have a converse then find the converse in the edges of the opposite face for (int fIdx = 0 ; fIdx < mesh.faces.size() ; fIdx++) { FVMeshFace& fvFace = mesh.faces[fIdx]; //FVMeshFaceHandle fh(mesh, fIdx); HE_FaceHandle fnew(*this, fIdx); // face index on FVMesh corresponds to index in HE_Mesh // HE_EdgeHandle edge = fnew.edge0(); // HE_EdgeHandle edgeStart = edge; // do // for (int eIdx = 0; eIdx < 3; eIdx++) { if (faceEdgeIsConnected[fIdx][eIdx]) { // edge.next(); continue; } int edge_idx = faces[fIdx].edge_idx[eIdx]; HE_Edge& edge = edges[ edge_idx ]; int face2 = fvFace.connected_face_index[eIdx]; // connected_face X is connected via vertex X and vertex X+1 if (face2 < 0) { atlas::logError("Incorrect model: disconnected faces. Support generation aborted.\n"); exit(1); // TODO: not exit, but continue without support! } for (int e2 = 0; e2 < 3; e2++) { if (mesh.faces[face2].vertex_index[e2] == edges[edge.next_edge_idx].from_vert_idx) { edges[ faces[face2].edge_idx[e2] ].converse_edge_idx = edge_idx; edge.converse_edge_idx = faces[face2].edge_idx[e2]; faceEdgeIsConnected[face2][e2] = true; // the other way around doesn't have to be set; we will not pass the same edge twice break; } if (e2 == 2) std::cerr << "Couldn't find converse of edge " << std::to_string(edge_idx) <<"!!!!!" << std::endl; } //edge = edge.next(); } //while (edge != edgeStart) } HE_MESH_DEBUG_DO( mesh.debugOutputWholeMesh(); ) }