//-------------------------------------------------------------------------------------------------- /// This needs to be rewritten because we need to test for crossing edges, not only point inside. /// In addition the test for polygon //-------------------------------------------------------------------------------------------------- bool FanEarClipTesselator::isTriangleValid(size_t u, size_t v, size_t w) { CVF_ASSERT(m_X > -1 && m_Y > -1); cvf::Vec3d A = (*m_nodeCoords)[u]; cvf::Vec3d B = (*m_nodeCoords)[v]; cvf::Vec3d C = (*m_nodeCoords)[w]; if ( m_areaTolerance > (((B[m_X]-A[m_X])*(C[m_Y]-A[m_Y])) - ((B[m_Y]-A[m_Y])*(C[m_X]-A[m_X]))) ) return false; std::list<size_t>::const_iterator c; for (c = m_polygonIndices.begin(); c != m_polygonIndices.end(); ++c) { // The polygon points that actually make up the triangle candidate does not count // (but the same points on different positions in the polygon does! ) // Todo so this test below is to accepting !! Bug !! if ( (*c == u) || (*c == v) || (*c == w)) continue; cvf::Vec3d P = (*m_nodeCoords)[*c]; if (isPointInsideTriangle(A, B, C, P)) return false; } return true; }
bool PAW::isPointInsideTriangleIndex(int px, int py, int triangleIndex){ //look for triangles in source landmarks int v1, v2, v3; v1 = triangles.at<int>(triangleIndex,0); v2 = triangles.at<int>(triangleIndex,1); v3 = triangles.at<int>(triangleIndex,2); int x1 = srcLandmarks.at<int>(v1,0); int y1 = srcLandmarks.at<int>(v1,1); int x2 = srcLandmarks.at<int>(v2,0); int y2 = srcLandmarks.at<int>(v2,1); int x3 = srcLandmarks.at<int>(v3,0); int y3 = srcLandmarks.at<int>(v3,1); return isPointInsideTriangle(px,py,x1,y1,x2,y2,x3,y3); }
bool EarClipTesselator::isTriangleValid( std::list<size_t>::const_iterator u, std::list<size_t>::const_iterator v, std::list<size_t>::const_iterator w) const { CVF_ASSERT(m_X > -1 && m_Y > -1); cvf::Vec3d A = (*m_nodeCoords)[*u]; cvf::Vec3d B = (*m_nodeCoords)[*v]; cvf::Vec3d C = (*m_nodeCoords)[*w]; if ( m_areaTolerance > (((B[m_X]-A[m_X])*(C[m_Y]-A[m_Y])) - ((B[m_Y]-A[m_Y])*(C[m_X]-A[m_X]))) ) return false; std::list<size_t>::const_iterator c; std::list<size_t>::const_iterator outside; for (c = m_polygonIndices.begin(); c != m_polygonIndices.end(); ++c) { // The polygon points that actually make up the triangle candidate does not count // (but the same points on different positions in the polygon does! // Except those one off the triangle, that references the start or end of the triangle) if ( (c == u) || (c == v) || (c == w)) continue; // Originally the below tests was not included which resulted in missing triangles sometimes outside = w; ++outside; if (outside == m_polygonIndices.end()) outside = m_polygonIndices.begin(); if (c == outside && *c == *u) { continue; } outside = u; if (outside == m_polygonIndices.begin()) outside = m_polygonIndices.end(); --outside; if (c == outside && *c == *w) { continue; } cvf::Vec3d P = (*m_nodeCoords)[*c]; if (isPointInsideTriangle(A, B, C, P)) return false; } return true; }
//returns how many triangles were inserted in the last recursion step int trueSeparateTriangles(Point* points, PhysicsObject* object, int currentTriangle, int size){ float* signals = (float*)malloc(size*sizeof(float)); int i=0; //verifies if any of the points is a concave point. we assumed that the points are given at counter-clockwise order for (i=0; i<size; i++) { int j = i-1<0?size-1:i-1; int k = i+1>=size?0:i+1; Point p1 = points[j]; Point p2 = points[i]; Point p3 = points[k]; signals[i] =(p2.x-p1.x)*(p3.y-p2.y)-(p3.x-p2.x)*(p2.y-p1.y); } char isConvex = 1; int removable = 0; for(i=0;i<size;i++){ if(signals[i]<0){//is a concave point, so the polygon is concave isConvex = 0; int j= i-1<0?size-1:i-1; if(signals[j]>0){//the point just before the concave one is an option for a triangle int k = j==0?size-1:j-1; char hasPointInside = 0; int l=0; for(l=0;l<size;l++){//check if the triangle has a point inside it if(l == i || l == j || l==k){ continue; } if(isPointInsideTriangle(points[i], points[j], points[k], points[l])){ hasPointInside = 1; break; } } if(hasPointInside){ continue; } //if everything is ok, add the triangle to the structure object->format.polygonInfo.triangles[currentTriangle][0] = points[i]; object->format.polygonInfo.triangles[currentTriangle][1] = points[j]; object->format.polygonInfo.triangles[currentTriangle][2] = points[k]; currentTriangle++; removable = j; break; } j = i+1>=size?0:i+1; if(signals[j]>0){//the point just after the concave one is an option for a triangle int k = j==size-1?0:j+1; char hasPointInside = 0; int l=0; for(l=0;l<size;l++){//check if the triangle has a point inside it if(l == i || l == j || l==k){ continue; } if(isPointInsideTriangle(points[i], points[j], points[k], points[l])){ hasPointInside = 1; break; } } if(hasPointInside){ continue; } //if everything is ok, add the triangle to the structure object->format.polygonInfo.triangles[currentTriangle][0] = points[i]; object->format.polygonInfo.triangles[currentTriangle][1] = points[j]; object->format.polygonInfo.triangles[currentTriangle][2] = points[k]; currentTriangle++; removable = j; break; } } } free(signals); //in the case object is convex, just fix a point and trace a line to all other points. if(isConvex){ int maxTriangles = size -2; for(i=0;i<maxTriangles; i++){ object->format.polygonInfo.triangles[currentTriangle][0] = points[0]; object->format.polygonInfo.triangles[currentTriangle][1] = points[i+1]; object->format.polygonInfo.triangles[currentTriangle][2] = points[i+2]; currentTriangle++; } return size-2; } //if is a concave structure Point* points2 = copyPoints(size, points); for(i=removable;i<size-1;i++){ points2[i] = points2[i+1]; } trueSeparateTriangles(points2, object, currentTriangle, size-1); free(points2); return 1; }
OZCOLLIDE_API bool testIntersectionTriBox(const Vec3f *_triPts[3], const Vec3f &_triNormal, const Box &_box, const Vec3f &_boxVel, float &_distTravel, Vec3f &_reaction) { int i, j; float d0, d1; float t; Plane tri_plane; tri_plane.fromPointAndNormal(*_triPts[0], _triNormal); Vec3f n_boxvel = _boxVel; n_boxvel.normalize(); if (_triNormal.dot(n_boxvel) > 0) return false; float minDist = FLT_MAX; int col = -1; // box vertices VS triangle for (i = 0; i < 8; i++) { Vec3f box_vertex = _box.getPoint(i); Vec3f box_vertex_normal = _box.getVertexNormal(i); if (box_vertex_normal.dot(n_boxvel) < -OZ_COS45) continue; float t; if (!tri_plane.intersectWithLine(box_vertex, box_vertex + n_boxvel, t) ) continue; if (t >= minDist) continue; if (t < 0) continue; Vec3f inter; inter = box_vertex + n_boxvel * t; if (!isPointInsideTriangle(*_triPts[0], *_triPts[1], *_triPts[2], inter)) continue; minDist = t; _reaction = _triNormal; col = 0; } // triangle vertices VS box faces for (i = 0; i < 3; i++) { float tnear, tfar; PLANE plane = intersectRayBox(*_triPts[i], -n_boxvel, _box, tnear, tfar); if (plane == -1) continue; if (tnear < 0) continue; if (tnear < minDist) { minDist = tnear; _reaction = -_box.getFaceNormal(plane); col = 1; } } // box edges VS triangle edges for (i = 0; i < 12; i++) { BoxEdge boxEdge = _box.getEdge(i); Plane boxEdgePlane; boxEdgePlane.fromPoints(boxEdge.p1, boxEdge.p0, boxEdge.p0 + _boxVel); Vec3f boxEdgeNormal = Vec3f(boxEdgePlane.a, boxEdgePlane.b, boxEdgePlane.c); Vec3f v0 = boxEdge.p1 - boxEdge.p0; for (j = 0; j < 3; j++) { const Vec3f *tpt0; const Vec3f *tpt1; tpt0 = _triPts[j]; if (j < 2) tpt1 = _triPts[j + 1]; else tpt1 = _triPts[0]; d0 = boxEdgePlane.dist(*tpt0); d1 = boxEdgePlane.dist(*tpt1); if (d0 * d1 > 0) continue; if (!boxEdgePlane.intersectWithLine(*tpt0, *tpt1, t)) continue; Vec3f v1 = *tpt1 - *tpt0; Vec3f ipt = *tpt0 + v1 * t; int a0 = 0, a1 = 1; float pl_x = fabsf(boxEdgePlane.a); float pl_y = fabsf(boxEdgePlane.b); float pl_z = fabsf(boxEdgePlane.c); if (pl_x > pl_y && pl_x > pl_z) { a0 = 1; a1 = 2; } else { if (pl_y > pl_z) { a0 = 0; a1 = 2; } } float dist = v0[a0] * (ipt[a1] - boxEdge.p0[a1]) - v0[a1] * (ipt[a0] - boxEdge.p0[a0]); float denom = v0[a1] * -n_boxvel[a0] - v0[a0] * -n_boxvel[a1]; if (!denom) continue; dist /= denom; if (dist < 0) continue; ipt -= dist * n_boxvel; Vec3f r1 = boxEdge.p0 - ipt; Vec3f r2 = boxEdge.p1 - ipt; if (r1.dot(r2) > 0) continue; if (dist < minDist) { minDist = dist; _reaction = v0 | v1; _reaction.normalize(); if (_reaction.dot(n_boxvel) > 0) _reaction = -_reaction; col = 2; } } } if (col == -1) return false; _distTravel = minDist; return true; }