void ShapeTest::firstCollision() { Scene3D scene; ShapeGroup3D shapes; Object3D a(&scene); Shape<Shapes::Sphere3D> aShape(a, {{1.0f, -2.0f, 3.0f}, 1.5f}, &shapes); Object3D b(&scene); Shape<Shapes::Point3D> bShape(b, {{3.0f, -2.0f, 3.0f}}, &shapes); Object3D c(&scene); Shape<Shapes::Composition3D> cShape(c, &shapes); /* No collisions initially */ CORRADE_VERIFY(!shapes.firstCollision(aShape)); CORRADE_VERIFY(!shapes.firstCollision(bShape)); CORRADE_VERIFY(!shapes.isDirty()); /* Move point into sphere */ b.translate(Vector3::xAxis(-1.0f)); /* Collision */ CORRADE_VERIFY(shapes.isDirty()); CORRADE_VERIFY(shapes.firstCollision(aShape) == &bShape); CORRADE_VERIFY(shapes.firstCollision(bShape) == &aShape); CORRADE_VERIFY(!shapes.isDirty()); }
void ShapeTest::collision() { Scene3D scene; ShapeGroup3D shapes; Object3D a(&scene); Shape<Shapes::Sphere3D> aShape(a, {{1.0f, -2.0f, 3.0f}, 1.5f}, &shapes); { /* Collision with point inside the sphere */ Shape<Shapes::Point3D> aShape2(a, {{1.0f, -2.0f, 3.0f}}, &shapes); shapes.setClean(); const Collision3D collision = aShape.collision(aShape2); CORRADE_VERIFY(collision); CORRADE_COMPARE(collision.position(), Vector3(1.0f, -2.0f, 3.0f)); } { /* No collision with point inside the sphere, but not in the same group */ ShapeGroup3D shapes2; Shape<Shapes::Point3D> aShape3(a, {{1.0f, -2.0f, 3.0f}}, &shapes2); shapes2.setClean(); CORRADE_VERIFY(!aShape.collision(aShape3)); } { CORRADE_EXPECT_FAIL("Should cross-scene collision work or not?"); /* No collision with point inside the sphere, but not in the same scene */ Scene3D scene2; Object3D c(&scene2); Shape<Shapes::Point3D> cShape(c, {{1.0f, -2.0f, 3.0f}}, &shapes); shapes.setClean(); CORRADE_VERIFY(!aShape.collision(cShape)); } { /* No collision with point outside of the sphere */ Object3D b(&scene); Shape<Shapes::Point3D> bShape(b, {{3.0f, -2.0f, 3.0f}}, &shapes); shapes.setClean(); CORRADE_VERIFY(!aShape.collision(bShape)); /* Move point inside the sphere -- collision */ b.translate(Vector3::xAxis(-1.0f)); shapes.setClean(); const Collision3D collision = aShape.collision(bShape); CORRADE_VERIFY(collision); CORRADE_COMPARE(collision.position(), Vector3(2.0f, -2.0f, 3.0f)); } }
/******************* TO DO 5 ********************* * BlendImages: * INPUT: * ipv: list of input images and their relative positions in the mosaic * blendWidth: width of the blending function * OUTPUT: * create & return final mosaic by blending all images * and correcting for any vertical drift */ CByteImage BlendImages(CImagePositionV& ipv, float blendWidth) { // Assume all the images are of the same shape (for now) CByteImage& img0 = ipv[0].img; CShape sh = img0.Shape(); int width = sh.width; int height = sh.height; int nBands = sh.nBands; int dim[2] = {width, height}; // Compute the bounding box for the mosaic int n = ipv.size(); float min_x = 0, min_y = 0; float max_x = 0, max_y = 0; int i; float dy = 0; for (i = 0; i < n; i++) { CTransform3x3 &pos = ipv[i].position; CVector3 corners[4];//表示图片的4个角的坐标,分别为左下,右下,左上,右上 corners[0][0] = 0.0; corners[0][1] = 0.0; corners[0][2] = 1.0; corners[1][0] = width - 1; corners[1][1] = 0.0; corners[1][2] = 1.0; corners[2][0] = 0.0; corners[2][1] = height - 1; corners[2][2] = 1.0; corners[3][0] = width - 1; corners[3][1] = height - 1; corners[3][2] = 1.0; corners[0] = pos * corners[0]; corners[1] = pos * corners[1]; corners[2] = pos * corners[2]; corners[3] = pos * corners[3]; corners[0][0] /= corners[0][2]; corners[0][1] /= corners[0][2]; corners[1][0] /= corners[0][2]; corners[1][1] /= corners[0][2]; corners[2][0] /= corners[0][2]; corners[2][1] /= corners[0][2]; corners[3][0] /= corners[0][2]; corners[3][1] /= corners[0][2]; // *** BEGIN TODO #1 *** // add some code here to update min_x, ..., max_y //Use c0 and c3 to get the range of x and y. int iminx, iminy, imaxx, imaxy; ImageBoundingBox(img0, pos, iminx, iminy, imaxx, imaxy); if (i == 0) { dy += imaxy; } if (i == n - 1) { dy -= imaxy; } /*if (min_x > corners[0][0]) { min_x = corners[0][0]; } if (max_x < corners[3][0]) { max_x = corners[3][0]; } if (min_y > corners[0][1]) { min_y = corners[0][1]; } if (max_y < corners[3][1]) { max_y = corners[3][1]; } */ min_x = min(min_x, float(iminx)); min_y = min(min_y, float(iminy)); max_x = max(max_x, float(imaxx)); max_y = max(max_y, float(imaxy)); // *** END TODO #1 *** } // Create a floating point accumulation image CShape mShape((int)(ceil(max_x) - floor(min_x)), (int)(ceil(max_y) - floor(min_y)), nBands); CFloatImage accumulator(mShape); accumulator.ClearPixels(); double x_init, x_final; double y_init, y_final; // Add in all of the images for (i = 0; i < n; i++) { CTransform3x3 &M = ipv[i].position; CTransform3x3 M_t = CTransform3x3::Translation(-min_x, -min_y) * M; CByteImage& img = ipv[i].img; // Perform the accumulation AccumulateBlend(img, accumulator, M_t, blendWidth); if (i == 0) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_init = p[0]; y_init = p[1]; } else if (i == n - 1) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_final = p[0]; y_final = p[1]; } } // Normalize the results CByteImage compImage(mShape); NormalizeBlend(accumulator, compImage); bool debug_comp = false; if (debug_comp) WriteFile(compImage, "tmp_comp.tga"); // Allocate the final image shape CShape cShape(mShape.width - width, height, nBands); CByteImage croppedImage(cShape); // Compute the affine deformation CTransform3x3 A = CTransform3x3(); // *** BEGIN TODO #2 *** // fill in the right entries in A to trim the left edge and // to take out the vertical drift A[0][2] = width /2; A[1][0] = dy / (mShape.width - width); // *** END TODO #2 *** // Warp and crop the composite WarpGlobal(compImage, croppedImage, A, eWarpInterpLinear); // WarpGlobal(compImage, croppedImage, A, eWarpInterpNearest); //similar as linear // WarpGlobal(compImage, croppedImage, A, eWarpInterpCubic); //all pixels are black return croppedImage; }
/******************* TO DO 5 ********************* * BlendImages: * INPUT: * ipv: list of input images and their relative positions in the mosaic * blendWidth: width of the blending function * OUTPUT: * create & return final mosaic by blending all images * and correcting for any vertical drift */ CByteImage BlendImages(CImagePositionV& ipv, float blendWidth) { // Assume all the images are of the same shape (for now) CByteImage& img0 = ipv[0].img; CShape sh = img0.Shape(); int width = sh.width; int height = sh.height; int nBands = sh.nBands; // int dim[2] = {width, height}; int n = ipv.size(); if (n == 0) return CByteImage(0,0,1); bool is360 = false; // Hack to detect if this is a 360 panorama if (ipv[0].imgName == ipv[n-1].imgName) is360 = true; // Compute the bounding box for the mosaic float min_x = FLT_MAX, min_y = FLT_MAX; float max_x = 0, max_y = 0; int i; for (i = 0; i < n; i++) { CTransform3x3 &T = ipv[i].position; // BEGIN TODO // add some code here to update min_x, ..., max_y printf("TODO: %s:%d\n", __FILE__, __LINE__); // END TODO } // Create a floating point accumulation image CShape mShape((int)(ceil(max_x) - floor(min_x)), (int)(ceil(max_y) - floor(min_y)), nBands + 1); CFloatImage accumulator(mShape); accumulator.ClearPixels(); double x_init, x_final; double y_init, y_final; // Add in all of the images for (i = 0; i < n; i++) { // Compute the sub-image involved CTransform3x3 &M = ipv[i].position; CTransform3x3 M_t = CTransform3x3::Translation(-min_x, -min_y) * M; CByteImage& img = ipv[i].img; // Perform the accumulation AccumulateBlend(img, accumulator, M_t, blendWidth); if (i == 0) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_init = p[0]; y_init = p[1]; } else if (i == n - 1) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_final = p[0]; y_final = p[1]; } } // Normalize the results mShape = CShape((int)(ceil(max_x) - floor(min_x)), (int)(ceil(max_y) - floor(min_y)), nBands); CByteImage compImage(mShape); NormalizeBlend(accumulator, compImage); bool debug_comp = false; if (debug_comp) WriteFile(compImage, "tmp_comp.tga"); // Allocate the final image shape int outputWidth = 0; if (is360) { outputWidth = mShape.width - width; } else { outputWidth = mShape.width; } CShape cShape(outputWidth, mShape.height, nBands); CByteImage croppedImage(cShape); // Compute the affine transformation CTransform3x3 A = CTransform3x3(); // identify transform to initialize // BEGIN TODO // fill in appropriate entries in A to trim the left edge and // to take out the vertical drift if this is a 360 panorama // (i.e. is360 is true) printf("TODO: %s:%d\n", __FILE__, __LINE__); // END TODO // Warp and crop the composite WarpGlobal(compImage, croppedImage, A, eWarpInterpLinear); return croppedImage; }