//test intersection using a rudimentary physics simulation //this drops a particle onto the terrain and it bounces around a bit int main() { Mercator::Terrain terrain; terrain.setBasePoint(0, 0, 2.8); terrain.setBasePoint(1, 0, 7.1); terrain.setBasePoint(0, 1, 0.2); terrain.setBasePoint(1, 1, 14.7); Mercator::Segment * segment = terrain.getSegment(0, 0); if (segment == 0) { std::cerr << "Segment not created by addition of required basepoints" << std::endl << std::flush; return 1; } segment->populate(); WFMath::Point<3> pos(30.0,30.0,100.0); //starting position WFMath::Vector<3> vel(0.0,1.0,0.0); //starting velocity WFMath::Vector<3> grav(0.0,0.0,-9.8); //gravity WFMath::Point<3> intersection; WFMath::Vector<3> intnormal; float timestep = 0.1; float e = 0.2; //elasticity of collision float totalT = 20.0; //time limit float par = 0.0; float t = timestep; while (totalT > timestep) { vel += t * grav; if (Mercator::Intersect(terrain, pos, vel * t, intersection, intnormal, par)) { //set pos to collision time, //less a small amout to keep objects apart pos = intersection - (vel * .01 * t); WFMath::Vector<3> impulse = intnormal * (Dot(vel, intnormal) * -2); std::cerr << "HIT" << std::endl; vel = (vel + impulse) * e; //not sure of the impulse equation, but this will do if (vel.sqrMag() < 0.01) { //stop if velocities are small std::cerr << "friction stop" << std::endl; break; } totalT -= par*t; t = (1.0-par)*t; } else { pos += vel*t; totalT -= t; t = timestep; } std::cerr << "timeLeft:" << totalT << " end pos" << pos << " vel" << vel << std::endl; } return 0; }
int main() { Mercator::Terrain t; // Add a null test shader to the terrain Mercator::Shader * shader = new TestShader; t.addShader(shader, 0); // Create a test area with a shape which intersects // the Segment at 0,0 Mercator::Area* a1 = new Mercator::Area(0, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), WFMath::Point<2>(3, 4)); p.addCorner(p.numCorners(), WFMath::Point<2>(10, 10)); p.addCorner(p.numCorners(), WFMath::Point<2>(14, 6)); p.addCorner(p.numCorners(), WFMath::Point<2>(18, 4)); p.addCorner(p.numCorners(), WFMath::Point<2>(17, 19)); p.addCorner(p.numCorners(), WFMath::Point<2>(6, 20)); p.addCorner(p.numCorners(), WFMath::Point<2>(-1, 18)); p.addCorner(p.numCorners(), WFMath::Point<2>(-8, 11)); a1->setShape(p); // Add enough base points to force the creation of the Segment at 0,0 t.setBasePoint(0, 0, -1); t.setBasePoint(0, 1, 8); t.setBasePoint(1, 0, 2); t.setBasePoint(1, 1, 11); // Get the Segment at 0,0 Mercator::Segment * seg = t.getSegment(0,0); assert(seg != 0); // Get the surfaces, and add one corresponding to the shader we added. // We need to do this as the functions that would normally make it happen // have been stubbed out. Mercator::Segment::Surfacestore & sss = seg->getSurfaces(); Mercator::Surface * sfce = new Mercator::Surface(*seg, *shader); // Force allocation of the surface buffer so we can check later that it // gets destroyed when the area is added to the terrain. sfce->allocate(); assert(sfce->isValid()); // Add the surface to the store for this segment sss[0] = sfce; // Add the area which should cause relevant surface date to be invalidated t.addArea(a1); // We assert this to ensure that the buffer has been de-allocated // by a call to Surface::invalidate caused by adding the Area. assert(!sfce->isValid()); // force the surface to re-allocate sfce->allocate(); assert(sfce->isValid()); // Modify the areas shape p.addCorner(p.numCorners(), WFMath::Point<2>(-9, 12)); a1->setShape(p); // and cause an area update t.updateArea(a1); // Check the surface has been invalidated again assert(!sfce->isValid()); // force the surface to re-allocate sfce->allocate(); assert(sfce->isValid()); t.removeArea(a1); // Check the surface has been invalidated again assert(!sfce->isValid()); }
int main() { Mercator::Terrain terrain; terrain.setBasePoint(0, 0, 2.8); terrain.setBasePoint(1, 0, 7.1); terrain.setBasePoint(0, 1, 0.2); terrain.setBasePoint(1, 1, 14.7); Mercator::Segment * segment = terrain.getSegment(0, 0); if (segment == 0) { std::cerr << "Segment not created by addition of required basepoints" << std::endl << std::flush; return 1; } segment->populate(); //test box definitely outside terrain WFMath::AxisBox<3> highab(WFMath::Point<3> (10.0, 10.0, segment->getMax() + 3.0), WFMath::Point<3> (20.0, 20.0, segment->getMax() + 6.1)); if (Mercator::Intersect(terrain, highab)) { std::cerr << "axisbox intersects with terrain even though it should be above it" << std::endl; return 1; } //test box definitely inside terrain WFMath::AxisBox<3> lowab(WFMath::Point<3> (10.0, 10.0, segment->getMin() - 6.1), WFMath::Point<3> (20.0, 20.0, segment->getMax() - 3.0)); if (!Mercator::Intersect(terrain, lowab)) { std::cerr << "axisbox does not intersect with terrain even though it should be below it" << std::endl; return 1; } //test axis box moved from above terrain to below it. bool inter=false; float dz = highab.highCorner()[2] - highab.lowCorner()[2] - 0.1; while (highab.highCorner()[2] > segment->getMin()) { highab.shift(WFMath::Vector<3>(0.0, 0.0, -dz)); if (Mercator::Intersect(terrain, highab)) { inter=true; break; } } if (!inter) { std::cerr << "axisbox passed through terrain with no intersection" << std::endl; return 1; } //test axisbox that spans two segments terrain.setBasePoint(0, 2, 4.8); terrain.setBasePoint(1, 2, 3.7); Mercator::Segment *segment2 = terrain.getSegment(0, 1); segment2->populate(); float segmax=std::max(segment->getMax(), segment2->getMax()); float segmin=std::min(segment->getMin(), segment2->getMin()); WFMath::AxisBox<3> ab(WFMath::Point<3> (50.0, 10.0, segmax + 3.0), WFMath::Point<3> (70.0, 20.0, segmax + 6.1)); if (Mercator::Intersect(terrain, ab)) { std::cerr << "axisbox2 intersects with terrain even though it should be above it" << std::endl; return 1; } WFMath::AxisBox<3> ab2(WFMath::Point<3> (50.0, 10.0, segmin - 6.1), WFMath::Point<3> (70.0, 20.0, segmin + 3.0)); if (!Mercator::Intersect(terrain, ab2)) { std::cerr << "axisbox2 does not intersect with terrain even though it should be below it" << std::endl; return 1; } WFMath::Point<3> intPoint; WFMath::Vector<3> intNorm; float par; //test vertical ray if (Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,0.0,50.0), intPoint, intNorm, par)) { std::cerr << "vertical ray intersected when it shouldnt" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,0.0,-50.0), intPoint, intNorm, par)) { std::cerr << "vertical ray didnt intersect when it should" << std::endl; return 1; } //test each quadrant if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(10.0,10.0,-100.0), intPoint, intNorm, par)) { std::cerr << "quad1 ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(10.0,-15.0,-50.0), intPoint, intNorm, par)) { std::cerr << "quad2 ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(-10.0,-10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "quad3 ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(-10.0,10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "quad4 ray didnt intersect when it should" << std::endl; return 1; } //test dx==0 and dy==0 if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "y+ ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,-10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "y- ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(-10.0,0.0,-50.0), intPoint, intNorm, par)) { std::cerr << "x- ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(10.0,0.0,-50.0), intPoint, intNorm, par)) { std::cerr << "x+ ray didnt intersect when it should" << std::endl; return 1; } //test a longer ray if (!Mercator::Intersect(terrain, WFMath::Point<3>(-10.08, -20.37, segmax + 3), WFMath::Vector<3>(100.0,183.0,-50.0), intPoint, intNorm, par)) { std::cerr << "long ray didnt intersect when it should" << std::endl; return 1; } //check the height value float h; WFMath::Vector<3> n; terrain.getHeightAndNormal(intPoint[0], intPoint[1], h, n); n.normalize(); if (n != intNorm) { std::cerr << "calculated normal is different from getHeightAndNormal" << std::endl; std::cerr << intPoint << std::endl; std::cerr << intNorm << "!=" << n << std::endl; // return 1; } // We can't check for equality here is it just doesn't work with // floats. Look it up in any programming book if you don't believe me. // - 20040721 <*****@*****.**> if (fabs(h - intPoint[2]) > 0.00001) { std::cerr << "calculated height is different from getHeightAndNormal" << std::endl; std::cerr << h << "!=" << intPoint[2] << std::endl; return 1; } return 0; }