const mydefs::Triangle3d TriangleIterator::operator*() { //////////////////////////////////////////////////////////////////////////////// int plus1mod3[3] = {1, 2, 0}; int minus1mod3[3] = {2, 0, 1}; #define org(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3] #define dest(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3] #define apex(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[(otri).orient + 3] //////////////////////////////////////////////////////////////////////////////// mydefs::Triangle3d triangle; TVertex v1; TVertex v2; TVertex v3; if( validTriangle() ) { org(mCurrentTriangle, v1); dest(mCurrentTriangle, v2); apex(mCurrentTriangle, v3); triangle = wykobi::make_triangle( v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]); } return triangle; }
bool TIN::findTriangle(double theX, double theY, mydefs::Triangle3d& theTriangle3d) const { //////////////////////////////////////////////////////////////////////////////// int plus1mod3[3] = {1, 2, 0}; int minus1mod3[3] = {2, 0, 1}; #define org(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3] #define dest(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3] #define apex(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[(otri).orient + 3] //////////////////////////////////////////////////////////////////////////////// bool result = false; TVertex v; TVertex t1; TVertex t2; TVertex t3; v = static_cast<TVertex>(new double[2]); v[0] = theX; v[1] = theY; if(preciselocate(mMesh, mBehavior, v, mRecentTri, 0) != OUTSIDE) { org(*mRecentTri, t1); dest(*mRecentTri, t2); apex(*mRecentTri, t3); theTriangle3d = wykobi::make_triangle(t1[0], t1[1], t1[2], t2[0], t2[1], t2[2], t3[0], t3[1], t3[2]); result = true; } delete [] v; return result; }
// Funnel algorithm void NavMap::funnel(Vector &start, Vector &end) { unTriangulatePath(); funnelVector.swap(std::vector<Vector>()); funnelVector.push_back(start); if(!intersectBounds(start, end)) { funnelVector.push_back(end); return; } portals.emplace(portals.begin(), start); portals.emplace(portals.begin(), start); portals.push_back(end); portals.push_back(end); Vector apex(start); Vector left(start); Vector right(start); int apexI = 0; int leftI = 0; int rightI = 0; Vector R; Vector L; for(unsigned int i = 2, j = 0; i < portals.size() && j < 1000; i+=2, j+=2){ if(!intersectBounds(apex, end)) { funnelVector.push_back(end); return; } Vector &pi1 = portals[i + 1]; Vector &pi = portals[i]; R = pi1 + (pi - pi1) * 0.99; L = pi + (pi1 - pi) * 0.99; if(triarea2(apex, right, R) <= 0.f) { if(Vector::equal(apex, right, 0.01f) || triarea2(apex, left, R) >= 0.f) { right = R; rightI = i; } else { funnelVector.push_back(left); apex = left; apexI = leftI; right = apex; rightI = apexI; i = apexI; break; } } if(triarea2(apex, left, L) >= 0.f) { if(Vector::equal(apex, left, 0.01f) || triarea2(apex, right, L) <= 0.f) { left = L; leftI = i; } else { funnelVector.push_back(right); apex = right; apexI = rightI; left = apex; leftI = apexI; i = apexI; break; } } } }
// This customized version carves holes defined by the regions. // It'll remove any element which doesn't receive any region. int custom_carveholes(struct mesh *m, struct behavior *b, const int *outside, const int *inside) { struct otri neighbortri; struct otri triangleloop; struct osub subsegloop; triangle **temptri; triangle ptr; /* Temporary variable used by sym(). */ double area; double attribute; double triangle_attribute; int sane_mesh; poolinit(& m->viri, sizeof( triangle * ), VIRUSPERBLOCK, VIRUSPERBLOCK, 0); /* Assigns every triangle a regional attribute of -1 */ traversalinit(& m->triangles); triangleloop.orient = 0; triangleloop.tri = triangletraverse(m); while ( triangleloop.tri != ( triangle * ) NULL ) { setelemattribute(triangleloop, m->eextras, -1.0); triangleloop.tri = triangletraverse(m); } sane_mesh = 1; /* Loop over all segments */ traversalinit(& m->subsegs); subsegloop.ss = subsegtraverse(m); subsegloop.ssorient = 0; while ( subsegloop.ss != ( subseg * ) NULL ) { if ( subsegloop.ss != m->dummysub ) { /* First neighbor. */ ssymself(subsegloop); stpivot(subsegloop, neighbortri); if ( neighbortri.tri != m->dummytri ) { area = 0.0; /// @todo Possible set this as the minimum as well. attribute = outside [ mark(subsegloop) - 1 ]; triangle_attribute = elemattribute(neighbortri, m->eextras); /* The region no number yet. */ if ( triangle_attribute < 0 && attribute >= 0 ) { infect(neighbortri); temptri = ( triangle ** ) poolalloc(& m->viri); * temptri = neighbortri.tri; /* Apply one region's attribute and/or area constraint. */ regionplague(m, b, attribute, area); /* The virus pool should be empty now. */ } else if ( attribute >= 0 && triangle_attribute >= 0 && attribute != triangle_attribute ) { /* Check for problems. */ vertex v1, v2, v3; org(neighbortri, v1); dest(neighbortri, v2); apex(neighbortri, v3); fprintf(stdout, "Error: inconsistent region information (new %d, old %d from %d) (outside) at (%e, %e)\n", ( int ) attribute, ( int ) triangle_attribute, ( int ) mark(subsegloop), ( v1 [ 0 ] + v2 [ 0 ] + v3 [ 0 ] ) / 3, ( v1 [ 1 ] + v2 [ 1 ] + v3 [ 1 ] ) / 3); sane_mesh = 0; } } /* Second neighbor (same procedure). */ ssymself(subsegloop); stpivot(subsegloop, neighbortri); if ( neighbortri.tri != m->dummytri ) { area = 0.0; attribute = inside [ mark(subsegloop) - 1 ]; triangle_attribute = elemattribute(neighbortri, m->eextras); if ( triangle_attribute < 0 && attribute >= 0 ) { infect(neighbortri); temptri = ( triangle ** ) poolalloc(& m->viri); * temptri = neighbortri.tri; regionplague(m, b, attribute, area); } else if ( attribute >= 0 && triangle_attribute >= 0 && attribute != triangle_attribute ) { vertex v1, v2, v3; org(neighbortri, v1); dest(neighbortri, v2); apex(neighbortri, v3); fprintf(stdout, "Error: inconsistent region information (new %d, old %d from %d) (inside) at (%e, %e)\n", ( int ) attribute, ( int ) triangle_attribute, ( int ) mark(subsegloop), ( v1 [ 0 ] + v2 [ 0 ] + v3 [ 0 ] ) / 3, ( v1 [ 1 ] + v2 [ 1 ] + v3 [ 1 ] ) / 3); sane_mesh = 0; } } subsegloop.ss = subsegtraverse(m); } } /* Remove all triangles with marker 0.0 */ traversalinit(& m->triangles); triangleloop.tri = triangletraverse(m); int triangle_number = 0; while ( triangleloop.tri != ( triangle * ) NULL ) { if ( triangleloop.tri != m->dummytri ) { triangle_number++; attribute = elemattribute(triangleloop, m->eextras); if ( attribute == -1.0 ) { fprintf(stderr, "Broken mesh at triangle %d\n", triangle_number); sane_mesh = 0; } else if ( attribute == 0.0 ) { infect(triangleloop); temptri = ( triangle ** ) poolalloc(& m->viri); * temptri = triangleloop.tri; } } triangleloop.tri = triangletraverse(m); } /* Remove the marked elements */ plague(m, b); if ( b->regionattrib && !b->refine ) { /* Note the fact that each triangle has an additional attribute. */ m->eextras++; } /* Free up memory. */ pooldeinit(& m->viri); return sane_mesh; }
void FunnelPlanner::computeCrossing( float radius, const Vector2 & startPos, PortalPath * path, size_t startPortal ) { assert( path->getPortalCount() > 0 && "Funnel planner should only be applied to PortalPaths with at least one portal" ); FunnelApex apex( startPortal - 1, startPos ); // if startPortal is zero, this should go to all 1s...i.e. -1 > all other size_t values const WayPortal * portal = path->getPortal( startPortal ); Vector2 pLeft( portal->getLeft( radius ) ); Vector2 pRight( portal->getRight( radius ) ); Vector2 dirLeft( pLeft - apex._pos ); Vector2 dirRight( pRight - apex._pos ); #ifdef SIMPLE_FUNNEL FunnelEdge funnelLeft( startPortal, dirLeft ); FunnelEdge funnelRight( startPortal, dirRight ); size_t currPortal = startPortal + 1; const size_t PORTAL_COUNT = path->getPortalCount(); while ( currPortal < PORTAL_COUNT ) { portal = path->getPortal( currPortal ); pLeft.set( portal->getLeft( radius ) ); pRight.set( portal->getRight( radius ) ); dirLeft.set( pLeft - apex._pos ); dirRight.set( pRight - apex._pos ); // test left side of the funnel if ( funnelRight.isOnRight( dirLeft ) ) { // the portal's funnel is on the right of the current funnel Vector2 oldApex = apex._pos; Vector2 newApex = funnelRight._dir + apex._pos; //if ( apex._id != -1 && apex._id < currPortal ) { path->setWaypoints( apex._id + 1, funnelRight._id + 1, newApex, norm( funnelRight._dir ) ); //} apex.set( funnelRight._id, newApex ); currPortal = funnelRight._id + 1; portal = path->getPortal( currPortal ); pLeft.set( portal->getLeft( radius ) ); pRight.set( portal->getRight( radius ) ); dirLeft.set( pLeft - apex._pos ); dirRight.set( pRight - apex._pos ); funnelLeft.set( currPortal, dirLeft ); funnelRight.set( currPortal, dirRight ); ++currPortal; continue; } else if ( funnelLeft.isOnRight( dirLeft ) ) { funnelLeft.set( currPortal, dirLeft ); } // test right side of the funnel if ( funnelLeft.isOnLeft( dirRight ) ) { // the portal's funnel is on the left of the current funnel Vector2 oldApex = apex._pos; Vector2 newApex = funnelLeft._dir + apex._pos; //if ( apex._id != -1 && apex._id < currPortal ) { path->setWaypoints( apex._id + 1, funnelLeft._id + 1, newApex, norm( funnelLeft._dir ) ); //} apex.set( funnelLeft._id, newApex ); currPortal = funnelLeft._id + 1; portal = path->getPortal( currPortal ); pLeft.set( portal->getLeft( radius ) ); pRight.set( portal->getRight( radius ) ); dirLeft.set( pLeft - apex._pos ); dirRight.set( pRight - apex._pos ); funnelLeft.set( currPortal, dirLeft ); funnelRight.set( currPortal, dirRight ); ++currPortal; continue; } else if ( funnelRight.isOnLeft( dirRight ) ) { funnelRight.set( currPortal, dirRight ); } ++currPortal; } // Now handle goal const Vector2 goalPt = path->getGoalCentroid(); Vector2 goalDir( goalPt - apex._pos ); if ( funnelLeft.isOnLeft( goalDir ) ) { // The goal point is on the left side of the funnel if ( apex._id != -1 && apex._id < PORTAL_COUNT ) { path->setWaypoints( apex._id + 1, PORTAL_COUNT, apex._pos + funnelLeft._dir, norm( funnelLeft._dir ) ); } } else if ( funnelRight.isOnRight( goalDir ) ) { // The goal point is on the right side of the funnel if ( apex._id != -1 && apex._id < PORTAL_COUNT ) { path->setWaypoints( apex._id + 1, PORTAL_COUNT, apex._pos + funnelRight._dir, norm( funnelRight._dir ) ); } } if ( apex._id + 1 < PORTAL_COUNT ) { path->setWaypoints( (size_t)apex._id + 1, (size_t)PORTAL_COUNT, goalPt, norm( goalPt - apex._pos ) ); } #else _left.push_back( FunnelEdge( startPortal - 1, startPortal, dirLeft, startPos ) ); _right.push_back( FunnelEdge( startPortal - 1, startPortal, dirRight, startPos ) ); const size_t PORTAL_COUNT = path->getPortalCount(); for ( size_t i = startPortal + 1; i < PORTAL_COUNT; ++i ) { portal = path->getPortal( i ); // investigate the left point pLeft.set( portal->getLeft( radius ) ); bool apexMoved = false; while ( !_right.empty() ) { std::list< FunnelEdge >::iterator itr = _right.begin(); Vector2 dir = pLeft - itr->_origin; if ( itr->isOnRight( dir ) ) { apexMoved = true; Vector2 newApex = itr->_origin + itr->_dir; path->setWaypoints( itr->_id + 1, itr->_endID + 1, newApex, norm( itr->_dir ) ); apex.set( itr->_endID, newApex ); _right.pop_front(); } else { break; } } if ( apexMoved ) { _left.clear(); _left.push_back( FunnelEdge( apex._id, i, pLeft - apex._pos, apex._pos ) ); } else { std::list< FunnelEdge >::reverse_iterator itr = _left.rbegin(); while ( ! _left.empty() ) { Vector2 dir = pLeft - itr->_origin; if ( itr->isOnRight( dir ) ) { _left.pop_back(); itr = _left.rbegin(); } else { break; } } if ( _left.empty() ) { _left.push_back( FunnelEdge( apex._id, i, pLeft - apex._pos, apex._pos ) ); } else { Vector2 origin( itr->_origin + itr->_dir ); _left.push_back( FunnelEdge( itr->_endID, i, pLeft - origin, origin ) ); } } // investigate the right point pRight.set( portal->getRight( radius ) ); apexMoved = false; while ( !_left.empty() ) { std::list< FunnelEdge >::iterator itr = _left.begin(); Vector2 dir = pRight - itr->_origin; if ( itr->isOnLeft( dir ) ) { apexMoved = true; Vector2 newApex = itr->_origin + itr->_dir; path->setWaypoints( itr->_id + 1, itr->_endID + 1, newApex, norm( itr->_dir ) ); apex.set( itr->_endID, newApex ); _left.pop_front(); } else { break; } } if ( apexMoved ) { _right.clear(); _right.push_back( FunnelEdge( apex._id, i, pRight - apex._pos, apex._pos ) ); } else { std::list< FunnelEdge >::reverse_iterator itr = _right.rbegin(); while ( ! _right.empty() ) { Vector2 dir = pRight - itr->_origin; if ( itr->isOnLeft( dir ) ) { _right.pop_back(); itr = _right.rbegin(); } else { break; } } if ( _right.empty() ) { _right.push_back( FunnelEdge( apex._id, i, pRight - apex._pos, apex._pos ) ); } else { Vector2 origin( itr->_origin + itr->_dir ); _right.push_back( FunnelEdge( itr->_endID, i, pRight - origin, origin ) ); } } } // handle the goal const Vector2 goalPt = path->getGoalCentroid(); Vector2 goalDir; bool apexMoved = false; while ( !_left.empty() ) { std::list< FunnelEdge >::iterator itr = _left.begin(); goalDir.set( goalPt - itr->_origin ); if ( itr->isOnLeft( goalDir ) ) { apexMoved = true; Vector2 newApex = itr->_origin + itr->_dir; apex.set( itr->_endID, newApex ); path->setWaypoints( itr->_id + 1, itr->_endID + 1, newApex, norm( itr->_dir ) ); _left.pop_front(); } else { break; } } if ( apexMoved ) { goalDir.set( goalPt - apex._pos ); path->setWaypoints( apex._id + 1, PORTAL_COUNT, goalPt, norm( goalDir ) ); } else { // apexMoved is already false -- it is the only way to reach this branch while ( !_right.empty() ) { std::list< FunnelEdge >::iterator itr = _right.begin(); goalDir.set( goalPt - itr->_origin ); if ( itr->isOnRight( goalDir ) ) { apexMoved = true; Vector2 newApex = itr->_origin + itr->_dir; apex.set( itr->_endID, newApex ); path->setWaypoints( itr->_id + 1, itr->_endID + 1, newApex, norm( itr->_dir ) ); _right.pop_front(); } else { break; } } goalDir.set( goalPt - apex._pos ); path->setWaypoints( apex._id + 1, PORTAL_COUNT, goalPt, norm( goalDir ) ); } #endif // SIMPLE_FUNNEL }
void Pyramid::createPyramid() { //Vertices Vect apex(0.0f, 7.07f, 0.0f); Vect frontLeft(-5.0f, 0.0f, 5.0f); Vect frontRight(5.0f, 0.0f, 5.0f); Vect backLeft(-5.0f, 0.0f, -5.0f); Vect backRight(5.0f, 0.0f, -5.0f); //Normals Vect frontNormal = (frontRight - frontLeft).cross(apex - frontRight); Vect rightNormal = (backRight - frontRight).cross(apex - backRight); Vect backNormal = (backLeft - backRight).cross(apex - backLeft); Vect leftNormal = (frontLeft - backLeft).cross(apex - frontLeft); Vect bottomNormal1 = (frontLeft - frontRight).cross(backLeft - frontLeft); Vect bottomNormal2 = (backRight - backLeft).cross(frontRight - backRight); pyramidBatch.Begin(GL_TRIANGLES, 18, 1); //Front side of pyramid //Front left pyramidBatch.Normal3f(frontNormal[x], frontNormal[y], frontNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f); pyramidBatch.Vertex3f(frontLeft[x], frontLeft[y], frontLeft[z]); //Front right pyramidBatch.Normal3f(frontNormal[x], frontNormal[y], frontNormal[z]); pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f); pyramidBatch.Vertex3f(frontRight[x], frontRight[y], frontRight[z]); //Apex pyramidBatch.Normal3f(frontNormal[x], frontNormal[y], frontNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f); pyramidBatch.Vertex3f(apex[x], apex[y], apex[z]); //Right side of pyramid //Front right pyramidBatch.Normal3f(rightNormal[x], rightNormal[y], rightNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f); pyramidBatch.Vertex3f(frontRight[x], frontRight[y], frontRight[z]); //Back right pyramidBatch.Normal3f(rightNormal[x], rightNormal[y], rightNormal[z]); pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f); pyramidBatch.Vertex3f(backRight[x], backRight[y], backRight[z]); //Apex pyramidBatch.Normal3f(rightNormal[x], rightNormal[y], rightNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f); pyramidBatch.Vertex3f(apex[x], apex[y], apex[z]); //Back side of pyramid //Back right pyramidBatch.Normal3f(backNormal[x], backNormal[y], backNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f); pyramidBatch.Vertex3f(backRight[x], backRight[y], backRight[z]); //Back left pyramidBatch.Normal3f(backNormal[x], backNormal[y], backNormal[z]); pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f); pyramidBatch.Vertex3f(backLeft[x], backLeft[y], backLeft[z]); //Apex pyramidBatch.Normal3f(backNormal[x], backNormal[y], backNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f); pyramidBatch.Vertex3f(apex[x], apex[y], apex[z]); //Left side of pyramid //Back left pyramidBatch.Normal3f(leftNormal[x], leftNormal[y], leftNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f); pyramidBatch.Vertex3f(backLeft[x], backLeft[y], backLeft[z]); //Front left pyramidBatch.Normal3f(leftNormal[x], leftNormal[y], leftNormal[z]); pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f); pyramidBatch.Vertex3f(frontLeft[x], frontLeft[y], frontLeft[z]); //Apex pyramidBatch.Normal3f(backNormal[x], backNormal[y], backNormal[z]); pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f); pyramidBatch.Vertex3f(apex[x], apex[y], apex[z]); //Bottom 1 of pyramid //Front right pyramidBatch.Normal3f(bottomNormal1[x], bottomNormal1[y], bottomNormal1[z]); pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f); pyramidBatch.Vertex3f(frontRight[x], frontRight[y], frontRight[z]); //Front left pyramidBatch.Normal3f(bottomNormal1[x], bottomNormal1[y], bottomNormal1[z]); pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f); pyramidBatch.Vertex3f(frontLeft[x], frontLeft[y], frontLeft[z]); //Back left pyramidBatch.Normal3f(bottomNormal1[x], bottomNormal1[y], bottomNormal1[z]); pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f); pyramidBatch.Vertex3f(backLeft[x], backLeft[y], backLeft[z]); //Bottom 2 of pyramid //Back left pyramidBatch.Normal3f(bottomNormal2[x], bottomNormal2[y], bottomNormal2[z]); pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f); pyramidBatch.Vertex3f(backLeft[x], backLeft[y], backLeft[z]); //Back right pyramidBatch.Normal3f(bottomNormal2[x], bottomNormal2[y], bottomNormal2[z]); pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f); pyramidBatch.Vertex3f(backRight[x], backRight[y], backRight[z]); //Front right pyramidBatch.Normal3f(bottomNormal2[x], bottomNormal2[y], bottomNormal2[z]); pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f); pyramidBatch.Vertex3f(frontRight[x], frontRight[y], frontRight[z]); pyramidBatch.End(); }
double TIN::interpolate(double theX, double theY) const { //////////////////////////////////////////////////////////////////////////////// int plus1mod3[3] = {1, 2, 0}; int minus1mod3[3] = {2, 0, 1}; #define org(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3] #define dest(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3] #define apex(otri, vertexptr) \ vertexptr = (vertex) (otri).tri[(otri).orient + 3] //////////////////////////////////////////////////////////////////////////////// double z; TVertex v; TVertex t1; TVertex t2; TVertex t3; wykobi::segment<double, 3> segment; wykobi::triangle<double, 3> triangle; v = static_cast<TVertex>(new double[2]); v[0] = theX; v[1] = theY; switch (preciselocate(mMesh, mBehavior, v, mRecentTri, 0)) { case ONVERTEX: org(*mRecentTri, t1); // Take elevation of vertex z = t1[2]; // delete [] t1; break; case ONEDGE: // Interpolate elevation on edge org(*mRecentTri, t1); dest(*mRecentTri, t2); segment = wykobi::make_segment(t1[0], t1[1], t1[2], t2[0], t2[1], t2[2]); z = interpolateOnSegment(segment, theX, theY); // delete [] t1; // delete [] t2; break; case INTRIANGLE: // Interpolate elevation on triangle org(*mRecentTri, t1); dest(*mRecentTri, t2); apex(*mRecentTri, t3); triangle = wykobi::make_triangle(t1[0], t1[1], t1[2], t2[0], t2[1], t2[2], t3[0], t3[1], t3[2]); z = interpolateInTriangle(triangle, theX, theY); // delete [] t1; // delete [] t2; // delete [] t3; break; case OUTSIDE: z = -1 * std::numeric_limits<double>::max(); break; } delete [] v; return z; }