From: <jl...@us...> - 2008-07-17 03:26:22
|
Revision: 3198 http://hugin.svn.sourceforge.net/hugin/?rev=3198&view=rev Author: jlegg Date: 2008-07-17 03:26:20 +0000 (Thu, 17 Jul 2008) Log Message: ----------- Started clipping faces for the TexCoordRemapper, still broken. Will be used for VertexCoordRemapper for circular crops at some point.Added buttons for the extra tools I will be adding. Added a display of the cropped region, similar to the old previews. Corrected a bug that caused misalignment by half a pixel. Improved accuracy of 'seam' detection for disk-like projections. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/crop_tool.png hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/crop_tool.svg hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/drag_tool.png hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/drag_tool.svg hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/identify_tool.png hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/identify_tool.svg Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-07-17 03:26:20 UTC (rev 3198) @@ -62,59 +62,53 @@ case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL: // Add any projections where the poles maps to a big set of points here. // check for pole crossing - /* (kind of) doesn't apply unless we have the poles near the view. - * The boundary correction of VertexCoordRemapper works over most - * of the the image, the top section may break the correction and - * will most likely contain a gap at the top. */ - if (view_state->GetOptions()->getVFOV() > 120.0) + { + OutputProjectionInfo *info = view_state->GetProjectionInfo(); + // get the pole in image coordinates + transform.createTransform(*(view_state->GetSrcImage(image_number)), + *(view_state->GetOptions())); + double img_x, img_y; + transform.transformImgCoord(img_x, img_y, + info->GetNorthPoleX(), + info->GetNorthPoleY()); + if ( img_y > 0.0 && img_y < height + && img_x > 0.0 && img_x < width) { - OutputProjectionInfo *info = view_state->GetProjectionInfo(); - // get the pole in image coordinates - transform.createTransform(*(view_state->GetSrcImage(image_number)), - *(view_state->GetOptions())); - double img_x, img_y; + pole = true; // it covers this pole + } + if (!pole) + { + // check the other pole transform.transformImgCoord(img_x, img_y, - info->GetNorthPoleX(), - info->GetNorthPoleY()); + info->GetSouthPoleX(), + info->GetSouthPoleY()); if ( img_y > 0.0 && img_y < height && img_x > 0.0 && img_x < width) { - pole = true; // it covers this pole + pole = true; // it covers this pole. } - if (!pole) + } + if (pole) + { + // the VertexCoordRemapper doesn't fair well with images where + // a single point on an image covers a range on the output. + // Use the TexCoordRemmaper instead. + if (selection != REMAP_TEX) { - // check the other pole - HuginBase::PanoramaOptions *opts = view_state->GetOptions(); - transform.transformImgCoord(img_x, img_y, - info->GetSouthPoleX(), - info->GetSouthPoleY()); - if ( img_y > 0.0 && img_y < height - && img_x > 0.0 && img_x < width) + selection = REMAP_TEX; + if (selected_remapper) { - pole = true; // it covers this pole. + delete selected_remapper; + selected_remapper = NULL; } + selected_remapper = new TexCoordRemapper(m_pano, + image_number, + view_state); } - if (pole) - { - // the VertexCoordRemapper doesn't fair well with images where - // a single point on an image covers a range on the output. - // Use the TexCoordRemmaper instead. - if (selection != REMAP_TEX) - { - selection = REMAP_TEX; - if (selected_remapper) - { - delete selected_remapper; - selected_remapper = NULL; - } - selected_remapper = new TexCoordRemapper(m_pano, - image_number, - view_state); - } - break; - } - // not breking to get a VertexCoordRemapper. + break; } + // not breking to get a VertexCoordRemapper. + } default: // A VertexCoordRemapper is generally the best. Create a new one // if we do not already have one. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-17 03:26:20 UTC (rev 3198) @@ -117,6 +117,9 @@ glColor3f(1.0, 1.0, 1.0); // draw each active image. int imgs = m_pano->getNrOfImages(); + // offset by a pixel + glPushMatrix(); + glTranslatef(0.5, 0.5, 0.0); glEnable(GL_TEXTURE_2D); m_tex_man->Begin(); // The old preview shows the lowest numbered image on top, so do the same: @@ -129,15 +132,38 @@ } m_tex_man->End(); glDisable(GL_TEXTURE_2D); - // draw lines down the middle + glPopMatrix(); + // darken the cropped out range + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glColor4f(0.0, 0.0, 0.0, 0.5); + // construct a strip of quads, with each pair being one of the corners. + const vigra::Rect2D roi = m_view_state->GetOptions()->getROI(); + glBegin(GL_QUAD_STRIP); + glVertex2f(0.0, 0.0); glVertex2i(roi.left(), roi.top()); + glVertex2f(width_o, 0.0); glVertex2i(roi.right(), roi.top()); + glVertex2f(width_o, height_o); glVertex2i(roi.right(), roi.bottom()); + glVertex2f(0.0, height_o); glVertex2i(roi.left(), roi.bottom()); + glVertex2f(0.0, 0.0); glVertex2i(roi.left(), roi.top()); + glEnd(); + // draw lines down the middle and around the cropped area. + // we want to invert the color to make it stand out. glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); - glEnable(GL_BLEND); + glColor3f(1.0, 1.0, 1.0); + // centre lines glBegin(GL_LINES); glVertex2f(width_o / 2.0, 0.0); glVertex2f(width_o / 2.0, height_o); glVertex2f(0.0, height_o / 2.0); glVertex2f(width_o, height_o / 2.0); glEnd(); + // border of cropped area. + glBegin(GL_LINE_LOOP); + glVertex2i(roi.left(), roi.top()); + glVertex2i(roi.right(), roi.top()); + glVertex2i(roi.right(), roi.bottom()); + glVertex2i(roi.left(), roi.bottom()); + glEnd(); glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp 2008-07-17 03:26:20 UTC (rev 3198) @@ -37,6 +37,10 @@ #include "ChoosyRemapper.h" #include <iostream> +// If we want to draw the outline of each face instead of shading it normally, +// uncomment this. Wireframe mode is for testing mesh quality. +// #define WIREFRAME + MeshManager::MeshManager(PT::Panorama *pano, ViewState *view_state_in) { m_pano = pano; @@ -153,16 +157,18 @@ glNewList(display_list_number, GL_COMPILE); remap->UpdateAndResetIndex(); std::cout << "Specifying faces.\n"; + #ifndef WIREFRAME glBegin(GL_QUADS); + #endif // get each face's coordinates from the remapper MeshRemapper::Coords coords; - // using line loops instead of quads so I can examine the - // meshes produced. while (remap->GetNextFaceCoordinates(&coords)) { number_of_faces++; // go in an anticlockwise direction - //glBegin(GL_LINE_LOOP); + #ifdef WIREFRAME + glBegin(GL_LINE_LOOP); + #endif glTexCoord2dv(coords.tex_c[0][0]); glVertex2dv(coords.vertex_c[0][0]); glTexCoord2dv(coords.tex_c[0][1]); @@ -171,9 +177,13 @@ glVertex2dv(coords.vertex_c[1][1]); glTexCoord2dv(coords.tex_c[1][0]); glVertex2dv(coords.vertex_c[1][0]); - //glEnd(); + #ifdef WIREFRAME + glEnd(); + #endif } + #ifndef WIREFRAME glEnd(); + #endif glEndList(); std::cout << "Prepared a display list for " << image_number << ", using " << number_of_faces << " face(s).\n"; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-17 03:26:20 UTC (rev 3198) @@ -20,9 +20,15 @@ * */ +#include <math.h> #include "MeshRemapper.h" #include "ViewState.h" +// The number of sides to give the regular sided polygon we use for circular +// clipping, higher is more accurate but slower. +const unsigned int circle_clip_detail = 32; +// the angle across each edge given the abpve. +const double circle_clip_inc = (double) circle_clip_detail / (2.0 * M_PI); MeshRemapper::MeshRemapper(HuginBase::Panorama *m_pano_in, unsigned int image_number_in, @@ -61,7 +67,16 @@ crop_x2 = (double) src->getCropRect().right() / width; crop_y1 = (double) src->getCropRect().top() / height; crop_y2 = (double) src->getCropRect().bottom() / height; - // TODO set variables for circular crop. + // set variables for circular crop. + circle_crop = src->getCropMode() == HuginBase::SrcPanoImage::CROP_CIRCLE; + if (circle_crop) + { + circle_crop_centre_x = (crop_x1 + crop_x2) / 2.0; + circle_crop_centre_y = (crop_y1 + crop_y2) / 2.0; + double width = crop_x2 - crop_x1, + height = crop_y2 - crop_y1; + circle_crop_radius = width < height ? width : height; + } // hugin allows negative cropping regions, but we are expected to only // output the regions that exist in the original image, so clamp the values: if (crop_x1 < 0.0) crop_x1 = 0.0; if (crop_x1 > 1.0) crop_x1 = 1.0; @@ -70,11 +85,266 @@ if (crop_y2 < 0.0) crop_y2 = 0.0; if (crop_y2 > 1.0) crop_y2 = 1.0; } -bool MeshRemapper::ClipFace(Coords *face) +/****************************************************************************** + * Clipping stuff * + ******************************************************************************/ + +// a vertex has vertex coordinates and a texture coordinates. +class Vertex { - // first clip to bounding quadrilatrial. We clip to each edge separately. - // TODO find the edges - // TODO clip - // TODO circlular clipping +public: + Vertex(double vx, double vy, double tx, double ty); + Vertex() {} + double vertex_c[2]; + double tex_c[2]; +}; + +Vertex::Vertex(double vx, double vy, double tx, double ty) +{ + vertex_c[0] = vx; + vertex_c[1] = vy; + tex_c[0] = tx; + tex_c[1] = ty; } +// The Polygon class stores an arbitrary polygon, and can give you another +// polygon that is the result of clipping it with some line. +class Polygon +{ +public: + // Create the polygon from a quadrilateral + Polygon(MeshRemapper::Coords *face); + Polygon() {} + // clip lines are the line defined by x * p[0] + y * p[1] + p[2] = 0. + // inside is the side where x * p[0] + y *p[1] + p[2] > 0. + Polygon Clip(const double clip_line[3]); + // add a vertex on the end of the list. Used to build the polygon when not + // created from a quad. + inline void AddVertex(Vertex v); + // convert to a list of quads. A bit approximate. + std::vector<MeshRemapper::ArrayCoords> ConvertToQuads(); +private: + // our list of vertices + std::vector<Vertex> verts; + // Test which side of the clip plane we are on + inline bool Inside(const unsigned int vertex, + const double clip_line[3]) const; + // given that the edge between the specified vertices crosses the clip line, + // find where they cross and set the vertex and texture coordinates there. + Vertex Intersect(const unsigned int v1, const unsigned int v2, + const double clip_line[3]) const; +}; + +Polygon::Polygon(MeshRemapper::Coords *face) +{ + verts.resize(4); + for (unsigned short int v = 0; v < 4; v++) + { + // give verticies counter-clockwise + unsigned short int x = (v == 2 || v==3) ? 1 : 0, + y = (v == 1 || v==2) ? 1 : 0; + for (unsigned short int a = 0; a < 2; a++) + { + verts[v].vertex_c[a] = face->vertex_c[x][y][a]; + verts[v].tex_c[a] = face->tex_c[x][y][a]; + } + } +} + +inline void Polygon::AddVertex(Vertex v) +{ + verts.push_back(v); +} + +inline bool Polygon::Inside(const unsigned int v, const double l[3]) const +{ + return verts[v].tex_c[0] * l[0] + verts[v].tex_c[1] * l[1] + l[2] > 0; +} + +Vertex Polygon::Intersect(const unsigned int v1_index, + const unsigned int v2_index, + const double cl[3]) const +{ + // find the point of intersection from the given edge with a clip plane. + // the edge is the vertex with the same number and the one before it. + // Get pointers to the vertecies we will use + const Vertex *v1 = &verts[v1_index], + // the vertex before is the last one if we at the beginning. + *v2 = &verts[v2_index]; + // find a vector along the path of the edge we are clipping + double dx = v2->tex_c[0] - v1->tex_c[0], + dy = v2->tex_c[1] - v1->tex_c[1]; + // The line along the edge we clip is defined by (x,y) = v1 + t(dx, dy) + // The line of the clipping plane is cl[0] * x + cl[1] * y + cl[2] = 0 + // now find what value of t that is on both lines. + // substitute x and y from the edge line into the equation of the clip line: + // cl[0] * (v1_x + t * dx) + cl[1] * (v1_y + t * dy) + cl[2] = 0 + // then rearrange to get t: expand: + // cl[0] * v1_x + t * cl[0] * dx + cl[1] * v1_y + t * cl[1] * dy + cl[2] = 0 + // t * (cl[0] * dx + cl[1] * dy) + cl[0] * v1_x + cl[1] * v1_y + cl[2] = 0 + // t * (cl[0] * dx + cl[1] * dy) = -cl[0] * v1_x - cl[1] * v1_y - cl[2] + // so we get: + DEBUG_ASSERT(cl[0] * dx + cl[1] * dy); + double t = (-cl[0] * v1->tex_c[0] - cl[1] * v1->tex_c[1] - cl[2]) / + (cl[0] * dx + cl[1] * dy), + // now substitute t into the edge we are testing's line: + x = dx * t + v1->tex_c[0], + y = dy * t + v1->tex_c[1], + // move the vertex coordinates to match the texture ones. + // t = 0 would give v1, t = 1 would give v2; so we linearly interpolate by t: + td1 = 1.0 - t, + xc = v1->vertex_c[0] * td1 + v2->vertex_c[0] * t, + yc = v1->vertex_c[1] * td1 + v2->vertex_c[1] * t; + return Vertex(xc, yc, x, y); +} + +Polygon Polygon::Clip(const double clip_line[3]) +{ + // We'll use the Sutherland-Hodgman clipping algorithm. + // see http://en.wikipedia.org/wiki/Sutherland-Hodgeman + Polygon result; + unsigned int vertices_count = verts.size(), + v_previous = vertices_count - 1; + // we want to examine all edges in turn, and find the vertices to keep: + for (unsigned int v_index = 0; v_index < vertices_count; v_index++) + { + if (Inside(v_index, clip_line)) + { + if (!Inside(v_previous, clip_line)) + { + // if we have one vertex in and one out, add the intersection. + result.AddVertex(Intersect(v_previous, v_index, clip_line)); + } + // keep any inner vertices + result.AddVertex(verts[v_index]); + } + else if (Inside(v_previous, clip_line)) + { + // if we have one vertex in and one out, add the intersection. + result.AddVertex(Intersect(v_previous, v_index, clip_line)); + } + v_previous = v_index; + } + return result; +} + +std::vector<MeshRemapper::ArrayCoords> Polygon::ConvertToQuads() +{ + // we want to convert any old polygon to quadrilaterals. + /* If the input was from a TexCoordRemapper, we'll have a rectangle with + * some edges chopped off, this could be empty, or a convex polygon. + * If we got our input from a VertexCoordRemapper it is likely to be (but + * not necessarily) convex. + * This is only guaranteed to work on convex polygons, though it will work + * some concave ones. + * FIXME Either use something more stable for concave polygons, or allow + * the Coords structure to take arbitrary polygons. + * Warning: The output of the clipping algorithm can create coincident lines + * where it has clipped through something concave. See this: + * http://en.wikipedia.org/wiki/Sutherland-Hodgman_clipping_algorithm + * It would be fine to leave those in if we don't mess up converting it to + * quadrilaterals (for example if sending the polygon directly to OpenGL) + */ + std::vector<MeshRemapper::ArrayCoords> result; + unsigned int vertices_count = verts.size(); + unsigned int i = 2; + // use vertex 0 for each face, and share another vertex with the last drawn, + // to (at least in convex cases) get the shape we intended, like this: + /* 0+------,7 + * /|\ c \ + * 1 / | \ \ 6 + * |a | \ | + * | | \| + * 2 \ | b / 5 + * \| / + * 3+------'4 + */ + while (i < vertices_count) + { + if (i < vertices_count - 1) + { + // make a new quadrilateral + MeshRemapper::ArrayCoords quad; + for (unsigned short int c = 0; c < 2; c++) + { + quad.vertex_c[0][0][c] = verts[ 0 ].vertex_c[c]; + quad.tex_c [0][0][c] = verts[ 0 ].tex_c [c]; + quad.vertex_c[0][1][c] = verts[i - 1].vertex_c[c]; + quad.tex_c [0][1][c] = verts[i - 1].tex_c [c]; + quad.vertex_c[1][1][c] = verts[ i ].vertex_c[c]; + quad.tex_c [1][1][c] = verts[ i ].tex_c [c]; + quad.vertex_c[1][0][c] = verts[i + 1].vertex_c[c]; + quad.tex_c [1][0][c] = verts[i + 1].tex_c [c]; + } + result.push_back(quad); + i += 2; + } + else + { + // make a new triangle, but repeat the last vertex so it is a quad + MeshRemapper::ArrayCoords quad; + for (unsigned short int c = 0; c < 2; c++) + { + quad.vertex_c[0][0][c] = verts[ 0 ].vertex_c[c]; + quad.tex_c [0][0][c] = verts[ 0 ].tex_c [c]; + quad.vertex_c[0][1][c] = verts[i - 1].vertex_c[c]; + quad.tex_c [0][1][c] = verts[i - 1].tex_c [c]; + quad.vertex_c[1][1][c] = verts[ i ].vertex_c[c]; + quad.tex_c [1][1][c] = verts[ i ].tex_c [c]; + quad.vertex_c[1][0][c] = verts[ i ].vertex_c[c]; + quad.tex_c [1][0][c] = verts[ i ].tex_c [c]; + } + result.push_back(quad); + i ++; + } + } + return result; +} + +std::vector<MeshRemapper::ArrayCoords> +MeshRemapper::ClipFace(MeshRemapper::Coords *face) +{ + // Clip the given face so that it only shows the cropped region of the + // source image. + // We use the texture coordinates to work out where to crop, and adjust the + // vertices locations accordingly. + + // convert the face to a polygon: + Polygon poly(face); + // work out where the clipping lines are, we use the cropping rectangle: + double clip_lines[4][3] = {{ 1.0, 0.0, -crop_x1}, + {-1.0, 0.0, crop_x2}, + { 0.0, 1.0, -crop_y1}, + { 0.0, -1.0, crop_y2}}; + // cut off each side + poly = poly.Clip(clip_lines[0]); + poly = poly.Clip(clip_lines[1]); + poly = poly.Clip(clip_lines[2]); + poly = poly.Clip(clip_lines[3]); + // Feign circular clipping by trimming to a many-sided regular polygon. + /* TODO We should get better circle cropping if we work out what angle to + * clip at based on the locations of the vertices. Then we could clip for + * the angles in the circle at each vertex and have far less clips, more + * detail, and reduce the number of vertices where the corners are as well. + * This will only break down where {a huge part / all / even more} of the + * image is contained within the input face, but then the interpolation + * there would make it well out of sync anyway, so it's no big deal. + */ + if (circle_crop) + { + for (unsigned int edge = 0; edge < circle_clip_detail; edge++) + { + double angle = (double) edge * circle_clip_inc, + ac_x = sin(angle), + ac_y = cos(angle), + // FIXME + clip_line[3] = {ac_x, ac_y, circle_crop_radius + - ac_x * circle_crop_centre_x + - ac_y * circle_crop_centre_y}; + poly = poly.Clip(clip_line); + } + } + // now convert to quadrilaterals. + return poly.ConvertToQuads(); +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-17 03:26:20 UTC (rev 3198) @@ -35,6 +35,7 @@ #ifndef _MESHREMAPPER_H #define _MESHREMAPPER_H +#include <vector> #include <panodata/Panorama.h> #include <panotools/PanoToolsInterface.h> @@ -56,9 +57,20 @@ // has some data structures already storing the values, and assignment // of a pointer is quicker than assignment of 8 doubles. The pointer is // used like an array to get the two different x positions though. + // the first actual array is the the positions in the opposite direction + // and the last array is x and y components of that vertex. + // tex_c is the coordinate in the image ranging from 0 to 1 + // vertex_c is the coordinate in the panorama, in its pixel space. double (*tex_c)[2][2]; double (*vertex_c)[2][2]; }; + class ArrayCoords + { + public: + // like above, but with it's own memory. + double tex_c[2][2][2]; + double vertex_c[2][2][2]; + }; // get the texture and vertex coordinates for the next face. The coordinates // are ordered [left / right][top / bottom][x coord / y coord]. // returns false once specified all faces. @@ -78,11 +90,13 @@ // cropping of the source image HuginBase::SrcPanoImage::CropMode crop_mode; - double crop_x1, crop_x2, crop_y1, crop_y2; + double crop_x1, crop_x2, crop_y1, crop_y2, + circle_crop_centre_x, circle_crop_centre_y, circle_crop_radius; + bool circle_crop; void SetCrop(); // fill the above values // crop a face to the source image, return true if there is anything left. // SetCrop() must have been called beforehand with up to date information. - bool ClipFace(Coords *face); + std::vector<ArrayCoords> ClipFace(Coords *face); }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-07-17 03:26:20 UTC (rev 3198) @@ -64,15 +64,33 @@ case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE: // The poles are on the sides. // ...or at least they can be detected from the sides (disk-likes) - // .. should be: FIXME these poles do not always detect images on - // the outer ring of disk projections. - transform.transformImgCoord(x, y, 0.0, 90.0); + // I've offset the noth pole slightly as the detection rate was + // not 100% + transform.transformImgCoord(x, y, 3.0, 90.0); north_pole_x = x; north_pole_y = y; transform.transformImgCoord(x, y, 360.0, 90.0); south_pole_x = x; south_pole_y = y; - break; + break; + case HuginBase::PanoramaOptions::RECTILINEAR: + // the pole and boundary like problems come at half the angle for + // rectilinear projections. + transform.transformImgCoord(x, y, 93.0, 90.0); + north_pole_x = x; + north_pole_y = y; + radius = -x + output->getSize()->x / 2.0; + transform.transformImgCoord(x, y, 270.0, 90.0); + south_pole_x = x; + south_pole_y = y; + + transform.transformImgCoord(x, y, 150.0, 90.0); + lower_x = x; + transform.transformImgCoord(x, y, 230.0, 90.0); + upper_x = x; + break; + default: + break; } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-07-17 03:26:20 UTC (rev 3198) @@ -26,7 +26,7 @@ #include <cstdlib> // higher values make the mesh more detailed, but slower and using more memory: -const double mesh_frequency = 0.1; +const double mesh_frequency = 0.0884; TexCoordRemapper::TexCoordRemapper(HuginBase::Panorama *m_pano, unsigned int image_number, @@ -67,6 +67,23 @@ { result->tex_c = texture_coords; result->vertex_c = vertex_coords; + // return remaining results of any previous clipping operation. + if (!face_list.empty()) + { + for (unsigned short int x = 0; x < 2; x++) + { + for (unsigned short int y = 0; y < 2; y++) + { + for (unsigned short int c = 0; c < 2; c++) + { + result->tex_c[x][y][0] = face_list.back().tex_c[x][y][0]; + result->vertex_c[x][y][0] = face_list.back().vertex_c[x][y][0]; + } + } + } + face_list.pop_back(); + return true; + } // try to find a face that is at least partly covered by the image. while (true) { @@ -88,15 +105,12 @@ } /* check if this quad shows any of the input image. * We could possibly drop some more faces, but this is a pretty good - * optimisation by itself. + * optimisation by itself. Proper clipping will alert us otherwise. */ if (!(all_left || all_right || all_above || all_below)) break; face_index++; } // now set the coordinates. - /* TODO clip to image. This will produce pentagons sometimes, so I'll have - * to split these into two quads and return them on two consecutive calls. - */ unsigned int x_f = face_index % (divisions_x - 1), y_f = face_index / (divisions_x - 1); for (unsigned short int x = 0; x < 2; x++) @@ -111,7 +125,36 @@ } } face_index++; - return true; + /* TODO Since we only crop to convex regions, having all four points + * inside the wanted region implies we don't need to do any clipping. It + * should be faster to test for this and skip full clipping in that case, + * as the vast majority of faces will not need any clipping. + */ + /* We have to clip the face to the source image. This may produce many faces + * or none, so we store a list and pop elements off it until the list is + * empty, or try from the top in the case we get none. + */ + face_list = ClipFace(result); + if (face_list.empty()) + { + // we clipped it all right off... try and get another face. + return GetNextFaceCoordinates(result); + } else { + // return a face from the result. + for (unsigned short int x = 0; x < 2; x++) + { + for (unsigned short int y = 0; y < 2; y++) + { + for (unsigned short int c = 0; c < 2; c++) + { + result->tex_c[x][y][0] = face_list.back().tex_c[x][y][0]; + result->vertex_c[x][y][0] = face_list.back().vertex_c[x][y][0]; + } + } + } + face_list.pop_back(); + return true; + } } void TexCoordRemapper::SetSize() @@ -127,10 +170,10 @@ // 1. If there is an efficient way to find a good bounding rectangle, use it // (I had a look at ComputeImageROI but seemed a bit brute force) // 2. With zooming, we could clip the stuff off the edge of the screen. - start_x = 0.0; - start_y = 0.0; - end_x = o_width; - end_y = o_height; + start_x = -0.5; + start_y = -0.5; + end_x = o_width - 0.5; + end_y = o_height - 0.5; // use the scale to determine edge lengths in pixels for subdivision scale = view_state->GetScale() * mesh_frequency; // round the number of divisions we need to get a whole number of faces @@ -140,9 +183,9 @@ if (divisions_y < 2) divisions_y = 2; // the face height and width uses the rounded number, we don't want gaps at // the edges of the panorama. Therefore scale is approximate now. - /* FIXME lines appear on the bottom edge when an image covers the top pole - * in equirectangular sometimes. These will get clipped when the FIXME above - * is done, but it means extra stuff is being done along the wrong edge. + /* FIXME there is a line on the bottom edge when an image covers the top + * pole in equirectangular sometimes. These will get clipped, but it means + * extra stuff is being done along a wrong edge. */ // the minus 1 is because we need the last division to cover the far edge. // note we have divisions_x - 1 faces to cover the divisions_x vertices. @@ -151,12 +194,8 @@ // work out the number of faces. number_of_faces = (divisions_x - 1) * (divisions_y - 1); // resize our data stucture for holding the vertex locations. - // FIXME I think this might be rather slow. Perhaps we need a data structure - // that only makes one new allocation here. - // This probably does 1 + divisions_x + divisions_x * divisions_y of them. - // I don't want to make my own until I'm sure this is actually slow. map.resize(divisions_x); - for (unsigned int column = 0; column < divisions_x; column++) + for (unsigned int column = 0; column < divisions_x; column++) { map[column].resize(divisions_y); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h 2008-07-17 03:26:20 UTC (rev 3198) @@ -58,6 +58,7 @@ unsigned int face_index, number_of_faces; double vertex_coords[2][2][2]; double texture_coords[2][2][2]; + std::vector<MeshRemapper::ArrayCoords> face_list; }; #endif Property changes on: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/crop_tool.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/crop_tool.svg =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/crop_tool.svg (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/crop_tool.svg 2008-07-17 03:26:20 UTC (rev 3198) @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="22" + height="22" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + version="1.0" + sodipodi:docname="crop_tool.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3169"> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="0" + id="stop3171" /> + <stop + id="stop3179" + offset="0.18367347" + style="stop-color:#000000;stop-opacity:0;" /> + <stop + style="stop-color:#000000;stop-opacity:0.78504676;" + offset="1" + id="stop3173" /> + </linearGradient> + <linearGradient + id="linearGradient3159"> + <stop + style="stop-color:#295c96;stop-opacity:1;" + offset="0" + id="stop3161" /> + <stop + style="stop-color:#75cbd9;stop-opacity:1;" + offset="1" + id="stop3163" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="24.545455" + inkscape:cx="11" + inkscape:cy="11" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1024" + inkscape:window-height="719" + inkscape:window-x="0" + inkscape:window-y="37"> + <inkscape:grid + type="xygrid" + id="grid2383" + visible="true" + enabled="true" + empspacing="2" + spacingx="0.5px" + spacingy="0.5px" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="opacity:1;fill:#80b3ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="rect2385" + width="40" + height="30" + x="2" + y="2" + transform="matrix(0.5,0,0,0.5333333,-1.05e-7,1.9333338)" /> + <path + style="fill:#165016;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 2,36 C 11.000002,44.500009 53.000006,27.250005 62.000007,35.875007 L 62,56 L 2,56 L 2,36 z" + id="path2387" + sodipodi:nodetypes="ccccc" + transform="matrix(0.3333333,0,0,0.347826,0.3333332,-0.4782601)" /> + <path + id="rect2753" + style="opacity:0.5;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" + d="M 0,0 L 22,0 L 22,22 L 0,22 L 0,0 zM 3.9999998,5.9999999 L 17.999999,5.9999999 L 17.999999,16 L 3.9999998,16 L 3.9999998,5.9999999 z" /> + <rect + style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.91494565999999999;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="rect3530" + width="14" + height="10" + x="4" + y="6" + transform="matrix(1.0764366,0,0,1.1097393,-0.8414607,-1.208436)" /> + <path + style="opacity:0.75;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 6 6 L 6 8 L 4 8 L 4 9 L 6 9 L 6 13 L 4 13 L 4 14 L 6 14 L 6 16 L 7 16 L 7 14 L 15 14 L 15 16 L 16 16 L 16 14 L 18 14 L 18 13 L 16 13 L 16 9 L 18 9 L 18 8 L 16 8 L 16 6 L 15 6 L 15 8 L 7 8 L 7 6 L 6 6 z M 7 9 L 15 9 L 15 13 L 7 13 L 7 9 z " + id="path3532" /> + </g> +</svg> Property changes on: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/drag_tool.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/drag_tool.svg =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/drag_tool.svg (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/drag_tool.svg 2008-07-17 03:26:20 UTC (rev 3198) @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="22" + height="22" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + version="1.0" + sodipodi:docname="drag_tool.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="/home/legg/gsoc/svn/hugin/src/hugin1/hugin/xrc/data/drag_tool.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow2Send" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow2Send" + style="overflow:visible;"> + <path + id="path3652" + style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;" + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " + transform="scale(0.3) rotate(180) translate(-2.3,0)" /> + </marker> + <marker + inkscape:stockid="Arrow2Mend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow2Mend" + style="overflow:visible;"> + <path + id="path3646" + style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;" + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " + transform="scale(0.6) rotate(180) translate(0,0)" /> + </marker> + <linearGradient + id="linearGradient3169"> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="0" + id="stop3171" /> + <stop + id="stop3179" + offset="0.18367347" + style="stop-color:#000000;stop-opacity:0;" /> + <stop + style="stop-color:#000000;stop-opacity:0.78504676;" + offset="1" + id="stop3173" /> + </linearGradient> + <linearGradient + id="linearGradient3159"> + <stop + style="stop-color:#295c96;stop-opacity:1;" + offset="0" + id="stop3161" /> + <stop + style="stop-color:#75cbd9;stop-opacity:1;" + offset="1" + id="stop3163" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="24.545455" + inkscape:cx="11" + inkscape:cy="11" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1024" + inkscape:window-height="719" + inkscape:window-x="0" + inkscape:window-y="37" + showguides="true" + inkscape:guide-bbox="true"> + <inkscape:grid + type="xygrid" + id="grid2383" + visible="true" + enabled="true" + empspacing="2" + spacingx="0.5px" + spacingy="0.5px" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <g + transform="matrix(0.9,0,0,1,3.1000002,2.0000041)" + id="g3608" + style="opacity:0.5"> + <rect + style="opacity:1;fill:#80b3ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="rect3610" + width="40" + height="30" + x="2" + y="2" + transform="matrix(0.5,0,0,0.5333333,-1.05e-7,1.9333338)" /> + <path + style="fill:#165016;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 2,36 C 11.000002,44.500009 53.000006,27.250005 62.000007,35.875007 L 62,56 L 2,56 L 2,36 z" + id="path3612" + sodipodi:nodetypes="ccccc" + transform="matrix(0.3333333,0,0,0.347826,0.3333332,-0.4782601)" /> + </g> + <g + id="g3604" + transform="matrix(0.9,0,0,1,-0.8999995,-1.9999917)"> + <rect + transform="matrix(0.5,0,0,0.5333333,-1.05e-7,1.9333338)" + y="2" + x="2" + height="30" + width="40" + id="rect2385" + style="opacity:1;fill:#80b3ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /> + <path + transform="matrix(0.3333333,0,0,0.347826,0.3333332,-0.4782601)" + sodipodi:nodetypes="ccccc" + id="path2387" + d="M 2,36 C 11.000002,44.500009 53.000006,27.250005 62.000007,35.875007 L 62,56 L 2,56 L 2,36 z" + style="fill:#165016;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + <path + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 23,16 L 23,21 L 18,21 L 19.5,19.5 L 16.5,16.5 L 18.5,14.5 L 21.5,17.5 L 23,16 z" + id="path4917" + sodipodi:nodetypes="cccccccc" + transform="translate(-2.9999997,-1.9999958)" /> + </g> +</svg> Property changes on: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/identify_tool.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/identify_tool.svg =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/identify_tool.svg (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/data/identify_tool.svg 2008-07-17 03:26:20 UTC (rev 3198) @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="22" + height="22" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + version="1.0" + sodipodi:docname="identify_tool.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="/home/legg/gsoc/svn/hugin/src/hugin1/hugin/xrc/data/crop_tool.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3169"> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="0" + id="stop3171" /> + <stop + id="stop3179" + offset="0.18367347" + style="stop-color:#000000;stop-opacity:0;" /> + <stop + style="stop-color:#000000;stop-opacity:0.78504676;" + offset="1" + id="stop3173" /> + </linearGradient> + <linearGradient + id="linearGradient3159"> + <stop + style="stop-color:#295c96;stop-opacity:1;" + offset="0" + id="stop3161" /> + <stop + style="stop-color:#75cbd9;stop-opacity:1;" + offset="1" + id="stop3163" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="29.409092" + inkscape:cx="10.999999" + inkscape:cy="11" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1024" + inkscape:window-height="719" + inkscape:window-x="0" + inkscape:window-y="37" + showguides="true" + inkscape:guide-bbox="true"> + <inkscape:grid + type="xygrid" + id="grid2383" + visible="true" + enabled="true" + empspacing="2" + spacingx="0.5px" + spacingy="0.5px" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="opacity:1;fill:#80b3ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="rect2385" + width="40" + height="30" + x="2" + y="2" + transform="matrix(0.5,0,0,0.5333333,-1.05e-7,1.9333338)" /> + <path + style="fill:#165016;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 2,36 C 11.000002,44.500009 53.000006,27.250005 62.000007,35.875007 L 62,56 L 2,56 L 2,36 z" + id="path2387" + sodipodi:nodetypes="ccccc" + transform="matrix(0.3333333,0,0,0.347826,0.3333332,-0.4782601)" /> + <rect + style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:0.91494566;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="rect3530" + width="19.508812" + height="15.318913" + x="4.0651336" + y="6.0877619" + transform="matrix(1.0764366,0,0,1.1097393,-3.8758588,-4.2558288)" /> + <rect + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="rect3581" + width="6" + height="9" + x="8" + y="6" + transform="matrix(1.4999999,0,0,1.3333333,-4.9999981,-2.9999998)" /> + <path + transform="matrix(0.9067136,0,0,0.9067136,6.4857164,5.0723972)" + style="font-size:12px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + d="M 4.9787315,9.8461111 L 4.9787315,3.2288065 L 3.3244054,3.7802486 L 3.3244054,2.6773645 L 4.9787315,2.1259225 L 6.0816156,2.1259225 L 6.0816156,9.8461111 L 8.2873838,9.8461111 L 8.3175411,10.948996 L 2.7729634,10.948995 L 2.7729634,9.8461111" + id="text3577" + sodipodi:nodetypes="ccccccccccc" /> + </g> +</svg> Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc 2008-07-16 06:35:14 UTC (rev 3197) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc 2008-07-17 03:26:20 UTC (rev 3198) @@ -405,7 +405,26 @@ <bitmap>data/photometric.png</bitmap> <tooltip>Use full photometric correction (slow)</tooltip> <label>Photometrics</label> - </object> + </object> + <object class="separator"/> + <object class="tool" name="preview_drag_tool"> + <toggle>1</toggle> + <bitmap>data/drag_tool.png</bitmap> + <tooltip>Drag images into position</tooltip> + <label>Drag</label> + </object> + <object class="tool" name="preview_crop_tool"> + <toggle>1</toggle> + <bitmap>data/crop_tool.png</bitmap> + <tooltip>Change the panorama's cropping region</tooltip> + <label>Crop</label> + </object> + <object class="tool" name="preview_identify_tool"> + <toggle>1</toggle> + <bitmap>data/identify_tool.png</bitmap> + <tooltip>Match images to their numbers</tooltip> + <label>Identify</label> + </object> <bitmapsize>22,22</bitmapsize> <packing>3</packing> <style>wxTB_DOCKABLE</style> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-18 03:11:03
|
Revision: 3203 http://hugin.svn.sourceforge.net/hugin/?rev=3203&view=rev Author: jlegg Date: 2008-07-18 03:10:59 +0000 (Fri, 18 Jul 2008) Log Message: ----------- Clipping now used for VertexCoordRemapper when using circular crop, still broken. When all points are inside the image, don't do clipping (works since cropping regions are convex). Moved some clipping related code to the MeshRemapper base class so both remappers can use it. VertexCoordRemapper now does not subdivide faces some distance away from the screen (a constant number of screen pixels, currently 10), and will consider differnce in length as well as angle when choosing when to subdivided otherwise. I've tried to fix the meeting of faces with different subdivision levels. The ViewState now holds the visible area of the panorama, which will be used for zooming and panning. Both MeshRemappers now respect this. When resizing the preview window significantly, recalculate the meshes with the new scale (previously you could enlarge a tiny window and it would show a low detail preview until you changed something). Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-18 03:10:59 UTC (rev 3203) @@ -93,6 +93,10 @@ glScissor(x_offs / scale, y_offs / scale, width_o / scale, height_o / scale); glMatrixMode(GL_MODELVIEW); + // tell the view state the region we are displaying. + // TODO add support for zooming and panning. + m_view_state->SetVisibleArea(vigra::Rect2D(0, 0, options->getWidth(), + options->getHeight())); return 1.0 / scale; } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp 2008-07-18 03:10:59 UTC (rev 3203) @@ -58,7 +58,8 @@ if (view_state->ImagesRemoved()) { CleanMeshes(); - // we can't trust anything after images have been removed + // we can't trust any meshes after images have been removed, they are + // indexed by image number, which could have changed. unsigned int num_images = m_pano->getNrOfImages(); for (unsigned int i = 0; i < num_images; i++) { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-18 03:10:59 UTC (rev 3203) @@ -179,7 +179,7 @@ // now find what value of t that is on both lines. // substitute x and y from the edge line into the equation of the clip line: // cl[0] * (v1_x + t * dx) + cl[1] * (v1_y + t * dy) + cl[2] = 0 - // then rearrange to get t: expand: + // then rearrange to get t: // cl[0] * v1_x + t * cl[0] * dx + cl[1] * v1_y + t * cl[1] * dy + cl[2] = 0 // t * (cl[0] * dx + cl[1] * dy) + cl[0] * v1_x + cl[1] * v1_y + cl[2] = 0 // t * (cl[0] * dx + cl[1] * dy) = -cl[0] * v1_x - cl[1] * v1_y - cl[2] @@ -208,20 +208,17 @@ // we want to examine all edges in turn, and find the vertices to keep: for (unsigned int v_index = 0; v_index < vertices_count; v_index++) { - if (Inside(v_index, clip_line)) + bool v_index_inside = Inside(v_index, clip_line), + v_previous_inside = Inside(v_previous, clip_line); + if (v_index_inside != v_previous_inside) { - if (!Inside(v_previous, clip_line)) - { - // if we have one vertex in and one out, add the intersection. - result.AddVertex(Intersect(v_previous, v_index, clip_line)); - } - // keep any inner vertices - result.AddVertex(verts[v_index]); + // one in, one out, therefore the edge instersts the clip line. + result.AddVertex(Intersect(v_previous, v_index, clip_line)); } - else if (Inside(v_previous, clip_line)) + if (v_index_inside) { - // if we have one vertex in and one out, add the intersection. - result.AddVertex(Intersect(v_previous, v_index, clip_line)); + // keep any inner vertices. + result.AddVertex(verts[v_index]); } v_previous = v_index; } @@ -301,8 +298,7 @@ return result; } -std::vector<MeshRemapper::ArrayCoords> -MeshRemapper::ClipFace(MeshRemapper::Coords *face) +void MeshRemapper::ClipFace(MeshRemapper::Coords *face) { // Clip the given face so that it only shows the cropped region of the // source image. @@ -337,7 +333,7 @@ double angle = (double) edge * circle_clip_inc, ac_x = sin(angle), ac_y = cos(angle), - // FIXME + // FIXME I think this defninition could be wrong: clip_line[3] = {ac_x, ac_y, circle_crop_radius - ac_x * circle_crop_centre_x - ac_y * circle_crop_centre_y}; @@ -345,6 +341,30 @@ } } // now convert to quadrilaterals. - return poly.ConvertToQuads(); + face_list = poly.ConvertToQuads(); } +bool MeshRemapper::GiveClipFaceResult(Coords * result) +{ + if (face_list.empty()) + { + // no more faces + return false; + } else { + // return a face + for (unsigned short int x = 0; x < 2; x++) + { + for (unsigned short int y = 0; y < 2; y++) + { + for (unsigned short int c = 0; c < 2; c++) + { + result->tex_c[x][y][0] = face_list.back().tex_c[x][y][0]; + result->vertex_c[x][y][0] = face_list.back().vertex_c[x][y][0]; + } + } + } + face_list.pop_back(); + return true; + } +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-18 03:10:59 UTC (rev 3203) @@ -96,7 +96,13 @@ void SetCrop(); // fill the above values // crop a face to the source image, return true if there is anything left. // SetCrop() must have been called beforehand with up to date information. - std::vector<ArrayCoords> ClipFace(Coords *face); + void ClipFace(Coords *face); + // Give a face that was produced by ClipFace and return true, or if there + // are no faces, return false. The pointers in result must be valid. + bool GiveClipFaceResult(Coords * result); +private: + // when clipping makes lots of faces, we need a list of them: + std::vector<MeshRemapper::ArrayCoords> face_list; }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-07-18 03:10:59 UTC (rev 3203) @@ -67,23 +67,8 @@ { result->tex_c = texture_coords; result->vertex_c = vertex_coords; - // return remaining results of any previous clipping operation. - if (!face_list.empty()) - { - for (unsigned short int x = 0; x < 2; x++) - { - for (unsigned short int y = 0; y < 2; y++) - { - for (unsigned short int c = 0; c < 2; c++) - { - result->tex_c[x][y][0] = face_list.back().tex_c[x][y][0]; - result->vertex_c[x][y][0] = face_list.back().vertex_c[x][y][0]; - } - } - } - face_list.pop_back(); - return true; - } + // return any remaining results of a previous clipping operation. + if (GiveClipFaceResult(result)) return true; // try to find a face that is at least partly covered by the image. while (true) { @@ -125,36 +110,35 @@ } } face_index++; - /* TODO Since we only crop to convex regions, having all four points - * inside the wanted region implies we don't need to do any clipping. It - * should be faster to test for this and skip full clipping in that case, - * as the vast majority of faces will not need any clipping. + /* Since we only crop to convex regions, having all four points inside the + * wanted region implies we don't need to do any clipping. It should be + * faster to test for this and skip full clipping in that case, as the vast + * majority of faces will not need any clipping. */ + HuginBase::SrcPanoImage *src_img = view_state->GetSrcImage(image_number); + if ( src_img->isInside(vigra::Point2D(int(result->tex_c[0][0][0] * width), + int(result->tex_c[0][0][1] * height))) + && src_img->isInside(vigra::Point2D(int(result->tex_c[0][1][0] * width), + int(result->tex_c[0][1][1] * height))) + && src_img->isInside(vigra::Point2D(int(result->tex_c[1][0][0] * width), + int(result->tex_c[1][0][1] * height))) + && src_img->isInside(vigra::Point2D(int(result->tex_c[1][1][0] * width), + int(result->tex_c[1][1][1] * height)))) + { + // all inside, doesn't need clipping. + return true; + } /* We have to clip the face to the source image. This may produce many faces * or none, so we store a list and pop elements off it until the list is * empty, or try from the top in the case we get none. */ - face_list = ClipFace(result); - if (face_list.empty()) + ClipFace(result); + if (GiveClipFaceResult(result)) { - // we clipped it all right off... try and get another face. - return GetNextFaceCoordinates(result); - } else { - // return a face from the result. - for (unsigned short int x = 0; x < 2; x++) - { - for (unsigned short int y = 0; y < 2; y++) - { - for (unsigned short int c = 0; c < 2; c++) - { - result->tex_c[x][y][0] = face_list.back().tex_c[x][y][0]; - result->vertex_c[x][y][0] = face_list.back().vertex_c[x][y][0]; - } - } - } - face_list.pop_back(); return true; - } + } else { + return GetNextFaceCoordinates(result); + } } void TexCoordRemapper::SetSize() @@ -162,18 +146,19 @@ const HuginBase::SrcPanoImage *src = view_state->GetSrcImage(image_number); width = (double) src->getSize().width(); height = (double) src->getSize().height(); - const HuginBase::PanoramaOptions *opts = view_state->GetOptions(); - o_width = (double) opts->getSize().width(); - o_height = (double) opts->getSize().height(); // set the bounding rectangle. // FIXME // 1. If there is an efficient way to find a good bounding rectangle, use it // (I had a look at ComputeImageROI but seemed a bit brute force) // 2. With zooming, we could clip the stuff off the edge of the screen. - start_x = -0.5; - start_y = -0.5; - end_x = o_width - 0.5; - end_y = o_height - 0.5; + // For now we stick with everything that is visible. + vigra::Rect2D visible_area = view_state->GetVisibleArea(); + start_x = (double) visible_area.left() - 0.5; + start_y = (double) visible_area.top() - 0.5; + end_x = (double) visible_area.right() - 0.5; + end_y = (double) visible_area.bottom() - 0.5; + o_width = end_x - start_x; + o_height = end_y - start_y; // use the scale to determine edge lengths in pixels for subdivision scale = view_state->GetScale() * mesh_frequency; // round the number of divisions we need to get a whole number of faces Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-07-18 03:10:59 UTC (rev 3203) @@ -56,12 +56,21 @@ // higher values are faster, lower ones more accurate. // TODO user preference? Increase during interactive changes? const double min_length = 4.0; -// the angle in radians under wich no subdivision occurs. Again, higher values -// will make it faster, lower ones will give higher accuracy. +// the angle in radians under which no subdivision occurs. Again, higher values +// will make it faster, lower ones will give higher accuracy. must be positive. const double min_angle = 0.05; +// the distance in absolute screen pixels between twice the length of the +// children and the length of the parent nodes, under which no subdivision +// occurs. higher values are faster, lower values give higher accuracy. Must be +// positive. +const double min_length_difference = 3.0; +// This is the margin around the edge of the screen in pixels, outside of which +// any face is not subdivided. Higher values are less likely to crop small +// features from the edge of the display, lower values add speed when there is +// faces that are significantly off-screen. It can be any number, but only +// positive numbers are recommended. +const double offscreen_safety_margin = 10.0; -const double huge_angle = 1.0; - template <class T> inline T sqr(T val) { @@ -126,6 +135,12 @@ bool VertexCoordRemapper::GetNextFaceCoordinates(Coords *result) { + result->tex_c = tex_coords; + result->vertex_c = s_vertex_coords; + // if we have some faces left over from a previous clipping operation, give + // one of those first: + if (GiveClipFaceResult(result)) return true; + // when 180 degree bounds correction is working, we'll have two nodes. if (done_node) { // this will search the tree for the next leaf node. @@ -137,7 +152,6 @@ } // find the coordinates from the tree node result->vertex_c = tree.nodes[tree_node_id].verts; - result->tex_c = tex_coords; tree.GetInputCoordinates(tree_node_id, tex_coords); // if the node has a discontinuity, we want to split it into two // faces and return each one on consecutive calls. @@ -181,6 +195,31 @@ } } } + // if we are doing circular cropping, clip the face so it makes the shape + if (circle_crop) + { + // If all points are within the radius, then don't clip + HuginBase::SrcPanoImage *src_img = view_state->GetSrcImage(image_number); + if ( src_img->isInside(vigra::Point2D(int(result->tex_c[0][0][0] * width), + int(result->tex_c[0][0][1] * height))) + && src_img->isInside(vigra::Point2D(int(result->tex_c[0][1][0] * width), + int(result->tex_c[0][1][1] * height))) + && src_img->isInside(vigra::Point2D(int(result->tex_c[1][0][0] * width), + int(result->tex_c[1][0][1] * height))) + && src_img->isInside(vigra::Point2D(int(result->tex_c[1][1][0] * width), + int(result->tex_c[1][1][1] * height)))) + { + // all inside, doesn't need clipping. + return true; + } + // we do need to clip: + ClipFace(result); + // if there was anything left, return the first face and leave the rest + // for later. + if (GiveClipFaceResult(result)) return true; + // we clipped to nothing... try and get another face: from the top... + return (GetNextFaceCoordinates(result)); + } return true; } @@ -188,13 +227,12 @@ { // we want to flip the given vertex to be the other side of the 180 degree // boundary, whatever the projection format. - // FIXME these are all silly aproximations. Often we assume the view is 360 - // degrees wide or tall. switch (output_projection) { case HuginBase::PanoramaOptions::RECTILINEAR: - vertex_c[1] *= -1.0; - vertex_c[0] *= -1.0; + // FIXME + //vertex_c[1] *= -1.0; + //vertex_c[0] *= -1.0; break; case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE: case HuginBase::PanoramaOptions::STEREOGRAPHIC: @@ -215,7 +253,7 @@ else vertex_c[0] -= x_add_360; break; case HuginBase::PanoramaOptions::SINUSOIDAL: - case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: + case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: if (vertex_c[0] < x_midpoint) { vertex_c[0] += @@ -296,9 +334,35 @@ node->verts[i][j][1], tex_coords[i][j][0] * width, tex_coords[i][j][1] * height); - // TODO where we need to patch up a gap caused by more - // subdivision above or to the left, use more faces rather - // than ignoring the problem. + // If the face results from a patch subdivision (for + // aligning a subdivided face, otherwise it need not exist), + // use the midpoint of the parent's vertices instead of + // calculating a transformed one, so we can use less + // subdivision on the other side. + // subdivision in x + if ( depth + && (parent->flags & patch_flag_x) + && !j + && !((i + x) % 2) + && y % 2) + { + node->verts[i][j][0] = (parent->verts[0][0][0] + + parent->verts[1][0][0]) / 2.0; + node->verts[i][j][1] = (parent->verts[0][0][1] + + parent->verts[1][0][1]) / 2.0; + } + // subdivision in y + if ( depth + && (parent->flags & patch_flag_y) + && !i + && !((j + y) % 2) + && x % 2) + { + node->verts[i][j][0] = (parent->verts[0][0][0] + + parent->verts[0][1][0]) / 2.0; + node->verts[i][j][1] = (parent->verts[0][0][1] + + parent->verts[0][1][1]) / 2.0; + } } } //std::cout << "(" << tex_coords[i][j][0] << ", " << tex_coords[i][j][1] << ") |-> (" << node->verts[i][j][0] << ", " << node->verts[i][j][1] << ")\n"; @@ -353,14 +417,13 @@ void VertexCoordRemapper::TestSubdivide(unsigned int node_id) { - // std::cout << "Testing subdivision for node " << node_id <<".\n"; + // FIXME with circular cropping we might not subdivide enough this way. TreeNode *node = &tree.nodes[node_id]; unsigned int x, y, row_size, depth; tree.GetPosition(node_id, x, y, row_size, depth); if (depth < min_depth) { // subdivide at least min_depth times - // std::cout << " under min_depth subdivisions, forcing subdivision.\n"; node->flags = split_flag_x | split_flag_y; // we will need more information for non-trivial children SetLengthAndAngle(node); @@ -369,7 +432,6 @@ if (depth == max_depth) { // don't subdivide more than max_depth times - // std::cout << " at maximum depth for subdivisions, forcing none.\n"; node->flags = 0; // TODO check for discontinuities return; @@ -391,32 +453,71 @@ { do_not_split_y = true; } + // if it has only subdivided to patch up between two subdivision levels, + // don't consider subdividing for adding more detail. + if (tree.nodes[parent_id].flags & patch_flag_x) + { + do_not_split_x = true; + } + else if (tree.nodes[parent_id].flags & patch_flag_y) + { + do_not_split_y = true; + } // if the angles have deviated too much from the parent then we should add // more detail, however if it is fairly flat then we don't need to. - // FIXME it is possible for the angles to remain constant but the length - // of the lines to change dramatically. Check parent for big difference - // in length of children? + // It is possible for the angles to remain constant but the length + // of the lines to change dramatically, so we check for a big difference + // between the length of the parent node and twice the length of child. + // if the child does not change the length much and the angle is small then + // we have enough detail so we don't split. float ang_x = node->angle_x - parent->angle_x; if (ang_x < 0) ang_x = -ang_x; if (ang_x > M_PI) ang_x = 2 * M_PI - ang_x; - if (ang_x < min_angle) + float length_difference_x = (parent->length_x - (2.0 * node->length_x)) * scale; + if (length_difference_x < 0.0) length_difference_x = -length_difference_x; + if (ang_x < min_angle && length_difference_x < min_length_difference) { do_not_split_x = true; } float ang_y = node->angle_y - parent->angle_y; if (ang_y < 0) ang_y = -ang_y; - if (ang_y > M_PI) ang_y = 2 * M_PI - ang_y; - if (ang_y < min_angle) + if (ang_y > M_PI) ang_y = 2 * M_PI - ang_y; + float length_difference_y = (parent->length_y - (2.0 * node->length_y)) * scale; + if (length_difference_y < 0.0) length_difference_y = -length_difference_y; + if (ang_y < min_angle && length_difference_y < min_length_difference) { do_not_split_y = true; } + // if the face is entirely off the screen, we should not subdivide it. + // get the screen area + vigra::Rect2D viewport = view_state->GetVisibleArea(); + // add a margin for safety, we don't want to clip stuff that curls back on. + // viewport.addBorder((int) (offscreen_safety_margin * scale)); + bool all_left = true, all_right = true, all_above = true, all_bellow = true; + for (unsigned int ix = 0; ix < 2; ix++) + { + for (unsigned int iy = 0; iy < 2; iy++) + { + if (node->verts[ix][iy][0] > viewport.left()) all_left = false; + if (node->verts[ix][iy][0] < viewport.right()) all_right = false; + if (node->verts[ix][iy][1] > viewport.top()) all_above = false; + if (node->verts[ix][iy][1] < viewport.bottom()) all_bellow = false; + } + } + if (all_left || all_right || all_bellow || all_above) + { + // all vertices are off a side of the screen. This catches most cases + // where the face is off the screen. Don't allow any subdivisions: + do_not_split_x = true; + do_not_split_y = true; + } unsigned short int flags = 0; if (!do_not_split_x) flags |= split_flag_x; if (!do_not_split_y) flags |= split_flag_y; /* Flag the vertices on a different side of the +/-180 degree seam. - * We don't want to flag any verticies if the face covers a continuous + * We don't want to flag any vertices if the face covers a continuous * area of the transformation. */ // We don't need to mark it unless it is a leaf node. @@ -432,7 +533,8 @@ { case HuginBase::PanoramaOptions::RECTILINEAR: // 60 degrees off centre in any direction? - if ( node->verts[0][0][0] < lower_bound + // FIXME? + /*if ( node->verts[0][0][0] < lower_bound || node->verts[0][0][0] > upper_bound || node->verts[1][0][0] < lower_bound || node->verts[1][0][0] > upper_bound @@ -496,7 +598,7 @@ flags |= vertex_side_flag_start * 8; } } - break; + break;*/ case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE: case HuginBase::PanoramaOptions::STEREOGRAPHIC: case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL: @@ -620,12 +722,11 @@ node->flags = flags; // check if the faces to the left are subdivided at a higher level - // TODO Not finished and FIXME wrong. - /*if (x && !(flags & split_flag_y)) + if (x && !(flags & split_flag_y)) { // scan back up the tree until we get something with a child node on the // left not containing this node. - unsigned int nid = node_id, depth_c = 0; + unsigned int nid = node_id, depth_c = 0.0; while ((nid % 2)) { nid = tree.GetParentId(nid); @@ -639,26 +740,72 @@ x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; // we'll need to deduce the location in y again. if (y_split && y2 != y >> (depth - depth2)) y2++; - // now we go right (and up and down a bit) - for (;depth_c; depth_c--) + nid = tree.GetIndex(x2, y2, row_size2, depth2); + if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; + // now we go right child until we get to the same depth, if there is + // enough splits in y. We also change heights to find the one we want. + for (;depth_c && y_split; depth_c--) { - x2*=2; - x2++; - y2*=2; - if (allow_y_shift && y2 != y >> (depth - depth2)) y2++; - row_size2 *= 2; - depth2++; - nid = tree.GetIndex(x2, y2, 1 << depth2, depth2); - if (!(tree.nodes[nid].flags & split_flag_y)) allow_y_shift = false; - if (!(tree.nodes[nid].flags & split_flag_x)) - { - break; - } + x2*=2; y2*=2; + row_size2 *= 2; depth2++; + // move across in x if there is a subdivision, stick to the right: + if ((tree.nodes[nid].flags & split_flag_x)) x2++; + // there will be a split in y, so work out which child gets us + // where we want to be: + if (y2 != y >> (depth - depth2)) y2++; + nid = tree.GetIndex(x2, y2, row_size2, depth2); + if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; } - // && (tree.nodes[node_id - 1].flags & split_flag_y)) - // we want to split just to line up with the other subdivision. - - }/**/ + if (y_split && !(tree.nodes[nid].flags & patch_flag_y)) + { + // more subdivision on the left. + // we want to split just to line up with the other subdivision. + node->flags |= split_flag_y | patch_flag_y; + } + } + // same for the other direction + if (y && !(flags & split_flag_x)) + { + // scan back up the tree until we get something with a child node on the + // top not containing this node. + unsigned int nid = node_id, depth_c, row_size2 = row_size; + while ((nid / row_size) % 2) + { + nid = tree.GetParentId(nid); + depth_c ++; + row_size /= 2; + } + // now go back down the tree + unsigned int x2, y2, depth2; + tree.GetPosition(nid, x2, y2, row_size2, depth2); + bool x_split = tree.nodes[nid].flags & split_flag_x; + // take the child not containing the node we are testing + x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; + // we'll need to deduce the location in x again. + if (x_split && x2 != x >> (depth - depth2)) x2++; + nid = tree.GetIndex(x2, y2, row_size2, depth2); + if (!(tree.nodes[nid].flags & split_flag_x)) x_split = false; + // now we take the downward child until we get to the same depth, if + // there is enough splits in x. We also change x location to find the + // one we want. + for (;depth_c && x_split; depth_c--) + { + x2*=2; y2*=2; + row_size2 *= 2; depth2++; + // move down in y if there is a subdivision + if ((tree.nodes[nid].flags & split_flag_y)) y2++; + // there will be a split in x, so find where we are + if (x2 != x >> (depth - depth2)) x2++; + nid = tree.GetIndex(x2, y2, row_size2, depth2); + if (!(tree.nodes[nid].flags & split_flag_x)) x_split = false; + } + if (x_split && !(tree.nodes[nid].flags & patch_flag_x)) + { + // more subdivision on the left. + // we want to split just to line up with the other subdivision. + node->flags |= split_flag_x | patch_flag_x; + } + } } void VertexCoordRemapper::SetLengthAndAngle(TreeNode *node) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp 2008-07-18 03:10:59 UTC (rev 3203) @@ -42,6 +42,7 @@ } opts = m_pano->getOptions(); projection_info = new OutputProjectionInfo(&opts); + genscale = 0.0; } ViewState::~ViewState() @@ -58,6 +59,26 @@ void ViewState::SetScale(float scale_in) { scale = scale_in; + // When resizing the window this can make the level detail of existing + // meshes be too high or low, but we don't want to do to much calculation + // so limit the forced recalculation of meshes to significant changes. + if (genscale == 0.0) + { + // should only happen the first time it is used. In which case we will + // regenerate the meshes anyways. + genscale = scale; + } else { + double difference = scale > genscale ? + scale / genscale : genscale / scale; + if (difference > 1.25) + { + genscale = scale; + for (unsigned int img = 0; img < number_of_images; img++) + { + dirty_mesh[img].val = true; + } + } + } } void ViewState::panoramaChanged(HuginBase::PanoramaData &pano) @@ -77,9 +98,7 @@ dirty_draw = true; active[img] = new_active; } - { } - } // has the number of images changed? if (imgs < number_of_images) { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-07-18 02:48:57 UTC (rev 3202) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-07-18 03:10:59 UTC (rev 3203) @@ -52,6 +52,7 @@ #include <panodata/PanoramaData.h> #include <panodata/Panorama.h> #include "OutputProjectionInfo.h" +#include <vigra/diff2d.hxx> class ViewState : public HuginBase::PanoramaObserver { @@ -97,9 +98,26 @@ // this is called when a draw has been performed, so we can assume the // drawing state (textures, meshes) are now all up to date. void FinishedDraw(); + + // The visible area is the part of the panarama visible in the view. The + // coordinates are in panorama pixels. + void SetVisibleArea(vigra::Rect2D area) + { + /* TODO with zooming, update meshes that were generated with this area + * in mind. Zooming changes the scale, which updates the meshes. + * Panning on the other hand needs to recalculate meshes as they can + * ignore the stuff off-screen + */ + visible_area = area; + } + vigra::Rect2D GetVisibleArea() + { + return visible_area; + } protected: HuginBase::Panorama *m_pano; - float scale; + float scale, genscale; + vigra::Rect2D visible_area; void (*RefreshFunc)(void *); void *refreshArg; std::map<unsigned int, HuginBase::SrcPanoImage> img_states; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-19 01:25:46
|
Revision: 3210 http://hugin.svn.sourceforge.net/hugin/?rev=3210&view=rev Author: jlegg Date: 2008-07-19 01:25:43 +0000 (Sat, 19 Jul 2008) Log Message: ----------- Slightly improved VertexCoordRemapper's subdivision and discontinuity handeling, fixed the setup for circular cropping. (Cropping still buggy) Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-18 14:15:51 UTC (rev 3209) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-19 01:25:43 UTC (rev 3210) @@ -76,6 +76,7 @@ double width = crop_x2 - crop_x1, height = crop_y2 - crop_y1; circle_crop_radius = width < height ? width : height; + circle_crop_radius /= 2.0; } // hugin allows negative cropping regions, but we are expected to only // output the regions that exist in the original image, so clamp the values: @@ -333,7 +334,6 @@ double angle = (double) edge * circle_clip_inc, ac_x = sin(angle), ac_y = cos(angle), - // FIXME I think this defninition could be wrong: clip_line[3] = {ac_x, ac_y, circle_crop_radius - ac_x * circle_crop_centre_x - ac_y * circle_crop_centre_y}; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-07-18 14:15:51 UTC (rev 3209) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-07-19 01:25:43 UTC (rev 3210) @@ -27,6 +27,9 @@ #include "panodata/SrcPanoImage.h" +/******************* + * Face's bit flags + *******************/ // split_x is set if the node has been split into two children (subdivided) in x const unsigned short int split_flag_x = 1; // patch_flag_x is set if we are patching a hole / overlap that could be caused @@ -45,13 +48,22 @@ const unsigned short int vertex_side_flag_start = 16; // 32, 64 and 128 are for the other vertices. -// range of acceptable subdivision stopping points -const unsigned int min_depth = 2; +/************************************* + * Detail / Acuracy / Speed Tradeoffs + *************************************/ +// Range of acceptable subdivision stopping points: +// Depth of forced subdivisions. Increase if there are transformations that show +// no signs of increasing detail level until subdivided more times, or cause +// problems with the seam detection. +const unsigned int min_depth = 4; +// Depth at which subdivision stops. // When adjusting also adjust this, also adjust the definition of Tree's nodes // to account for the extra memory required. A high value uses more memory, -// a low value limits the detail. +// a low value limits the detail. The amount of elements in the array should be +// the sum from n = 0 to max_depth of 4^n. (so for n=6, 1+4+16+64+256+2048+4096) const unsigned int max_depth = 6; + // this is the length in screen pixels under which no subdivision occurs. // higher values are faster, lower ones more accurate. // TODO user preference? Increase during interactive changes? @@ -170,7 +182,7 @@ tree.nodes[tree_node_id].verts[x][y][0]; s_vertex_coords[x][y][1] = tree.nodes[tree_node_id].verts[x][y][1]; - if (discontinuity_flags & (1 << (x * 2 + y))) + if (discontinuity_flags & (1 << (x*2 + y))) { DiscontinuityFlip(s_vertex_coords[x][y]); } @@ -188,7 +200,7 @@ tree.nodes[tree_node_id].verts[x][y][0]; s_vertex_coords[x][y][1] = tree.nodes[tree_node_id].verts[x][y][1]; - if (!(discontinuity_flags & (1 << (x * 2 + y)))) + if (!(discontinuity_flags & (1 << (x*2 + y)))) { DiscontinuityFlip(s_vertex_coords[x][y]); } @@ -340,28 +352,36 @@ // calculating a transformed one, so we can use less // subdivision on the other side. // subdivision in x - if ( depth + // FIXME there are still gaps. I think there's a logic error + if ( depth // not on the top level. + // patching in y && (parent->flags & patch_flag_x) - && !j - && !((i + x) % 2) - && y % 2) + // we must be in the middle of the split, the nodes on + // the corners of the parent line up anyway. + && ((i + x) % 2) + // we should be on the side away from the subdivison + // (+ve y). + && j + // If we are split in y we can use the middle + // node to provide more detail. + && !(parent->flags & split_flag_y && (y % 2))) { - node->verts[i][j][0] = (parent->verts[0][0][0] - + parent->verts[1][0][0]) / 2.0; - node->verts[i][j][1] = (parent->verts[0][0][1] - + parent->verts[1][0][1]) / 2.0; + node->verts[i][1][0] = (parent->verts[0][1][0] + + parent->verts[1][1][0]) / 2.0; + node->verts[i][1][1] = (parent->verts[0][1][1] + + parent->verts[1][1][1]) / 2.0; } // subdivision in y if ( depth && (parent->flags & patch_flag_y) - && !i - && !((j + y) % 2) - && x % 2) + && ((j + y) % 2) + && i + && !((x % 2) && parent->flags & split_flag_x)) { - node->verts[i][j][0] = (parent->verts[0][0][0] - + parent->verts[0][1][0]) / 2.0; - node->verts[i][j][1] = (parent->verts[0][0][1] - + parent->verts[0][1][1]) / 2.0; + node->verts[i][1][0] = (parent->verts[1][0][0] + + parent->verts[1][1][0]) / 2.0; + node->verts[i][1][1] = (parent->verts[1][0][1] + + parent->verts[1][1][1]) / 2.0; } } } @@ -421,101 +441,117 @@ TreeNode *node = &tree.nodes[node_id]; unsigned int x, y, row_size, depth; tree.GetPosition(node_id, x, y, row_size, depth); + unsigned short int flags = 0; if (depth < min_depth) { // subdivide at least min_depth times - node->flags = split_flag_x | split_flag_y; // we will need more information for non-trivial children SetLengthAndAngle(node); - return; - } - if (depth == max_depth) - { - // don't subdivide more than max_depth times - node->flags = 0; - // TODO check for discontinuities - return; - } - unsigned int parent_id = tree.GetParentId(node_id); - TreeNode *parent = &tree.nodes[parent_id]; - // minimum length check. We use the length of the top edge to test for - // subdivision in x, and the length of the left edge for subdivision in y. - SetLengthAndAngle(node); - bool do_not_split_x = node->length_x * scale < min_length, - do_not_split_y = node->length_y * scale < min_length; - // if we have stopped splitting in some direction, don't consider splitting - // in that direction again. - if (!(tree.nodes[parent_id].flags & split_flag_x)) - { - do_not_split_x = true; - } - else if (!(tree.nodes[parent_id].flags & split_flag_y)) - { - do_not_split_y = true; - } - // if it has only subdivided to patch up between two subdivision levels, - // don't consider subdividing for adding more detail. - if (tree.nodes[parent_id].flags & patch_flag_x) - { - do_not_split_x = true; - } - else if (tree.nodes[parent_id].flags & patch_flag_y) - { - do_not_split_y = true; - } + flags |= split_flag_x | split_flag_y; + } else { + unsigned int parent_id = tree.GetParentId(node_id); + TreeNode *parent = &tree.nodes[parent_id]; + // minimum length check. We use the length of the top edge to test for + // subdivision in x, and the length of the left edge for subdivision in + // y. + SetLengthAndAngle(node); + bool do_not_split_x = node->length_x * scale < min_length, + do_not_split_y = node->length_y * scale < min_length; + if (depth == max_depth) + { + // don't subdivide more than max_depth times + do_not_split_x = true; + do_not_split_y = true; + } + // if we have stopped splitting in some direction, don't consider + // splitting in that direction again. + if (!(tree.nodes[parent_id].flags & split_flag_x)) + { + do_not_split_x = true; + } + else if (!(tree.nodes[parent_id].flags & split_flag_y)) + { + do_not_split_y = true; + } + // if it has only subdivided to patch up between two subdivision levels, + // don't consider subdividing for adding more detail. + if (tree.nodes[parent_id].flags & patch_flag_x) + { + do_not_split_x = true; + } + else if (tree.nodes[parent_id].flags & patch_flag_y) + { + do_not_split_y = true; + } - // if the angles have deviated too much from the parent then we should add - // more detail, however if it is fairly flat then we don't need to. - // It is possible for the angles to remain constant but the length - // of the lines to change dramatically, so we check for a big difference - // between the length of the parent node and twice the length of child. - // if the child does not change the length much and the angle is small then - // we have enough detail so we don't split. - float ang_x = node->angle_x - parent->angle_x; - if (ang_x < 0) ang_x = -ang_x; - if (ang_x > M_PI) ang_x = 2 * M_PI - ang_x; - float length_difference_x = (parent->length_x - (2.0 * node->length_x)) * scale; - if (length_difference_x < 0.0) length_difference_x = -length_difference_x; - if (ang_x < min_angle && length_difference_x < min_length_difference) - { - do_not_split_x = true; - } - float ang_y = node->angle_y - parent->angle_y; - if (ang_y < 0) ang_y = -ang_y; - if (ang_y > M_PI) ang_y = 2 * M_PI - ang_y; - float length_difference_y = (parent->length_y - (2.0 * node->length_y)) * scale; - if (length_difference_y < 0.0) length_difference_y = -length_difference_y; - if (ang_y < min_angle && length_difference_y < min_length_difference) - { - do_not_split_y = true; - } - // if the face is entirely off the screen, we should not subdivide it. - // get the screen area - vigra::Rect2D viewport = view_state->GetVisibleArea(); - // add a margin for safety, we don't want to clip stuff that curls back on. - // viewport.addBorder((int) (offscreen_safety_margin * scale)); - bool all_left = true, all_right = true, all_above = true, all_bellow = true; - for (unsigned int ix = 0; ix < 2; ix++) - { - for (unsigned int iy = 0; iy < 2; iy++) + // If the angles have deviated too much from the parent then we should + // add more detail, however if it is fairly flat then we don't need to. + // It is possible for the angles to remain constant but the length + // of the lines to change dramatically, so we check for a big difference + // between the length of the parent node and twice the length of child. + // if the child does not change the length much and the angle is small, + // then we have enough detail, and we don't split. + float ang_x = node->angle_x - parent->angle_x; + if (ang_x < 0) ang_x = -ang_x; + if (ang_x > M_PI) ang_x = 2 * M_PI - ang_x; + float length_difference_x + = (parent->length_x - (2.0 * node->length_x)) * scale; + if (length_difference_x < 0.0) { - if (node->verts[ix][iy][0] > viewport.left()) all_left = false; - if (node->verts[ix][iy][0] < viewport.right()) all_right = false; - if (node->verts[ix][iy][1] > viewport.top()) all_above = false; - if (node->verts[ix][iy][1] < viewport.bottom()) all_bellow = false; + length_difference_x = -length_difference_x; } + if (ang_x < min_angle && length_difference_x < min_length_difference) + { + do_not_split_x = true; + } + float ang_y = node->angle_y - parent->angle_y; + if (ang_y < 0) ang_y = -ang_y; + if (ang_y > M_PI) ang_y = 2 * M_PI - ang_y; + float length_difference_y + = (parent->length_y - (2.0 * node->length_y)) * scale; + if (length_difference_y < 0.0) + { + length_difference_y = -length_difference_y; + } + if (ang_y < min_angle && length_difference_y < min_length_difference) + { + do_not_split_y = true; + } + // if the face is entirely off the screen, we should not subdivide it. + // get the screen area + vigra::Rect2D viewport = view_state->GetVisibleArea(); + // add a margin for safety, we don't want to clip too much stuff that + // curls back on to the screen. We add 2 as we need some space around + // very small panoramas that have enlarged to fit the preview window, + // and even with a fairly large margin rounding to int may lose the + // border completely. + viewport.addBorder((int) (2.0 + offscreen_safety_margin * scale)); + bool all_left = true, all_right = true, + all_above = true, all_bellow = true; + for (unsigned int ix = 0; ix < 2; ix++) + { + for (unsigned int iy = 0; iy < 2; iy++) + { + if (node->verts[ix][iy][0] > viewport.left()) + all_left = false; + if (node->verts[ix][iy][0] < viewport.right()) + all_right = false; + if (node->verts[ix][iy][1] > viewport.top()) + all_above = false; + if (node->verts[ix][iy][1] < viewport.bottom()) + all_bellow = false; + } + } + if (all_left || all_right || all_bellow || all_above) + { + // all vertices are off a side of the screen. This catches most + // cases where the face is off the screen. Don't allow subdivisions: + do_not_split_x = true; + do_not_split_y = true; + } + if (!do_not_split_x) flags |= split_flag_x; + if (!do_not_split_y) flags |= split_flag_y; } - if (all_left || all_right || all_bellow || all_above) - { - // all vertices are off a side of the screen. This catches most cases - // where the face is off the screen. Don't allow any subdivisions: - do_not_split_x = true; - do_not_split_y = true; - } - unsigned short int flags = 0; - if (!do_not_split_x) flags |= split_flag_x; - if (!do_not_split_y) flags |= split_flag_y; - /* Flag the vertices on a different side of the +/-180 degree seam. * We don't want to flag any vertices if the face covers a continuous * area of the transformation. @@ -597,8 +633,8 @@ { flags |= vertex_side_flag_start * 8; } - } - break;*/ + }*/ + break; case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE: case HuginBase::PanoramaOptions::STEREOGRAPHIC: case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL: @@ -722,7 +758,7 @@ node->flags = flags; // check if the faces to the left are subdivided at a higher level - if (x && !(flags & split_flag_y)) + if (x && !(flags & split_flag_y) && depth < max_depth) { // scan back up the tree until we get something with a child node on the // left not containing this node. @@ -764,7 +800,7 @@ } } // same for the other direction - if (y && !(flags & split_flag_x)) + if (y && !(flags & split_flag_x) && depth < max_depth) { // scan back up the tree until we get something with a child node on the // top not containing this node. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h 2008-07-18 14:15:51 UTC (rev 3209) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h 2008-07-19 01:25:43 UTC (rev 3210) @@ -166,7 +166,8 @@ unsigned int depth, unsigned int stop_x, unsigned int stop_y, double &dest_x, double &dest_y); - + // Array of as many nodes necessary to store a full tree with subdivions + // up to max_depth (defined in VertexCoordRemapper.cpp) times. TreeNode nodes[1+4+16+64+256+1024+4096]; private: unsigned int cur_tree_node; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-21 21:16:46
|
Revision: 3213 http://hugin.svn.sourceforge.net/hugin/?rev=3213&view=rev Author: jlegg Date: 2008-07-21 21:16:43 +0000 (Mon, 21 Jul 2008) Log Message: ----------- Now check for validity of transformations using the VertexCoordRemapper. When used with a patched libpano13, this fixes problems with rectilinear output. More work done on patching where the subdivision level decreases. Begun writing framework for tools. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-07-21 21:16:43 UTC (rev 3213) @@ -0,0 +1,59 @@ +// -*- c-basic-offset: 4 -*- + +/** @file PreviewTool.h + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* PreviewTool is an abstract base class for the interactive tools that work + * with the OpenGL accelerated preview. They can respond to the users actions + * over the preview, or changes in the panorama, and can draw extras above, + * below, or instead of the panorama images. + */ + +#include "PreviewToolHelper.h" + +class PreviewTool +{ +public: + // when inhereting, please use this: + PreviewTool(PreviewToolHelper *helper); + // Lots of stub functions here. Your tools should override a few of them. + + /* When the user switches on the tool, Activate is called. We should + * register events we want to respond to with the helper when activating, + * these are lost when the tool is deactivated, but we are not notified. */ + virtual void Activate() = 0; + + // These are called when events happen, providing we requested notification. + // The coordinates are in the space of the panorama output at full size. + virtual void MouseMoveEvent(double x, double y) {} + virtual void MouseButtonEvent(unsigned short int button, bool pressed) {} + virtual void KeypressEvent(int keycode, bool pressed) {} + // In the next few events we are free to draw stuff in OpenGL. + virtual void BeforeDrawImagesEvent() {} + virtual void AfterDrawImagesEvent() {} + // if the tool uses this event to draw the image itself, return false. + // otherwise, return true and the image will be drawn normally. + // Use this, for example, to the in-order drawing + virtual bool BeforeDrawImageEvent() {} + // called just after the image was drawn normally. + virtual void AfterDrawImageEvent() {} +protected: + PreviewToolHelper *helper; +} Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-21 21:16:43 UTC (rev 3213) @@ -0,0 +1,43 @@ +// -*- c-basic-offset: 4 -*- + +/** @file PreviewToolHelper.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#include "PreviewToolHelper.h" +#include "PreviewTool.h" + +PreviewToolHelper::PreviewToolHelper(HuginBase::Panorama *pano_in, + ViewState *view_state_in) +{ + pano = pano_in; + view_state = view_state_in; +} + +PreviewToolHelper::~PreviewToolHelper() +{ +} + +std::vector<PreviewTool> ActivateTool::(PreviewTool *tool) +{ + tools_deactivated.clear(); + tool.Activate(); + return tools_deactivated; +} Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-21 21:16:43 UTC (rev 3213) @@ -0,0 +1,113 @@ +// -*- c-basic-offset: 4 -*- + +/** @file PreviewToolHelper.h + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* A preview tool helper manages information that any tool may want to use, + * and guides the interaction between tools. These features are available: + * - Notification of user events: + * - When the mouse moves + * - When the mouse button is pressed / released. + * - When a key is pressed / released + * - Notifications when drawing things on the preview, allowing: + * - Drawing under / above the set of images. + * - Drawing under / above each individual image. + * - Replacing or stopping the drawing of each individual image. + * - Notification of when: + * - The tool is activated. + * - The tool is deactivated. + * - The tool has to give up some event notifications. + * (when another tool requests them, we don't want two different things + * responding to the same mouse click for example) + * - The tool can request the mouse position. + * - The tool can request a list of images under the mouse. + * - The tool can access the panorama, and make changes to it. + * - The tool can access the ViewState. This allows it to respond to, and cause, + * interactive changes. + * - The tool can deactivate itself, for example, when asked to give up events. + * - Possible extensions: + * - What images have been selected + * - Provide a menu over the preview + */ + +#ifndef _PREVIEWTOOLHELPER_H +#define _PREVIEWTOOLHELPER_H + +#include <wx/defs.h> +#include <vector> +#include <string> + +#include "ViewState.h" + +class PreviewTool; + +class PreviewToolHelper +{ +public: + enum Event + { + MOUSE_MOVE, MOUSE_PRESS, KEY_PRESS, + REDRAW_REQURIED, DRAW_UNDER_IMAGES, DRAW_OVER_IMAGES, + MESH_CHANGE, + // each image has it's own event numeration, starting with this one: + DRAW_IMAGE_0 + }; + PreviewToolHelper(HuginBase::Panorama *pano, + ViewState *view_state); + ~PreviewToolHelper(); + // working with tools + void AddTool(PreviewTool *tool); + // Activate a tool, the tool will then request notifications it needs. + // Then return a list of tools that had to be dactivated to comply. + std::vector<*PreviewTool> ActivateTool(PreviewTool *tool); + // deactivate a tool: remove all it's notifications. + void DeactivateTool(PreviewTool *tool); + + // Events + void MouseMoved(unsigned int x, unsigned int y); + // pressed is true if the button is pushed down, false if let go + void MouseButtonEvent(unsigned short int button, bool pressed); + // keycode is the wxWidgets keycode. + void KeypressEvent(int keycode, bool pressed); + void BeforeDrawImages(); + void AfterDrawImages(); + // Return true if we want it drawn, return false and draw the image as the + // tools specify otherwise. + bool BeforeDrawImageNumber(); + void AfterDrawImageNumber(); + + // Get information + std::vector<unsigned int> GetImageNumbersUnderMouse(); + pair<unsigned int, unsigned int> GetMousePosition(); + ViewState *GetViewStatePtr(); + HuginBase::Panorama *GetPanoramaPtr(); + + // Setting up notifications + NotifyMe(Event *event, Tool *tool); + DoNotNotifyMe(Event *event, PreviewTool *tool); + +private: + std::vector<*PreviewTool> tools_deactivated; + HuginBase::Panorama *pano; + ViewState *view_state; + unsigned int mouse_x, mouse_y; +} + +#endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-07-20 02:10:45 UTC (rev 3212) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-07-21 21:16:43 UTC (rev 3213) @@ -282,7 +282,6 @@ if (texinfo->min_lod != mip_level) { // maximum level required changed. - texinfo->SetMaxLevel(mip_level); if (texinfo->min_lod > mip_level) { // generate more levels @@ -292,6 +291,7 @@ photometric_correct, dest_img, view_state->GetSrcImage(image_index)); } + texinfo->SetMaxLevel(mip_level); texinfo->min_lod = mip_level; } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-07-20 02:10:45 UTC (rev 3212) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-07-21 21:16:43 UTC (rev 3213) @@ -47,8 +47,16 @@ // flagged we get the other. const unsigned short int vertex_side_flag_start = 16; // 32, 64 and 128 are for the other vertices. +// if the tranformation can't find a result, we set flags to indicate the +// vertices we had a problem with. +const unsigned short int transform_fail_flag = 256; +// 512, 1024, and 2048 are for the other vertices +/* where we have a set of flags refering to different vertices, vertex [x][y] + * corresponds with first_vertex_flag << (y * 2 + x). + */ + /************************************* * Detail / Acuracy / Speed Tradeoffs *************************************/ @@ -115,11 +123,6 @@ // {x|y}_add_360's are added to a value near the left/top boundary to get // the corresponding point over the right/bottom boundary. // other values are used to check where the boundary is. - // FIXME not suitble for Rectilinear projections. - /* FIXME these are dependent on the output image and not the input images. - * move to something independent of the images to avoid needless - * recalculation. - */ OutputProjectionInfo *info = view_state->GetProjectionInfo(); x_add_360 = info->GetXAdd360(); radius = info->GetRadius(); @@ -155,15 +158,24 @@ // when 180 degree bounds correction is working, we'll have two nodes. if (done_node) { - // this will search the tree for the next leaf node. - tree_node_id = tree.GetNext(); - if (!tree_node_id) + do { - // we've reached last one - return false; + // this will search the tree for the next leaf node. + tree_node_id = tree.GetNext(); + if (!tree_node_id) + { + // we've reached last one + return false; + } } + // some of the verticies may have arrived from undefined transformations + // if this is one, skip it and try to find another. + while ((tree.nodes[tree_node_id].flags & (transform_fail_flag * 15))); + // find the coordinates from the tree node result->vertex_c = tree.nodes[tree_node_id].verts; + // check that the transformation is properly defined. + tree.GetInputCoordinates(tree_node_id, tex_coords); // if the node has a discontinuity, we want to split it into two // faces and return each one on consecutive calls. @@ -242,18 +254,16 @@ switch (output_projection) { case HuginBase::PanoramaOptions::RECTILINEAR: - // FIXME - //vertex_c[1] *= -1.0; - //vertex_c[0] *= -1.0; + // There is no 180 degree boundary for rectilinear projections. + // Anything containing a vertex beyond 90 degrees (i.e. behind the + ///viewer) is not drawn. break; case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE: case HuginBase::PanoramaOptions::STEREOGRAPHIC: case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL: - // circular projections. We want to find the distance from the - // 180 degree circle and use it the other direction of the other - // side. - vertex_c[1] *= -1.0; - vertex_c[0] *= -1.0; + // circular projections. These stretch rather nastily over the + // centre, and correcting them doesn't help much, so any image + // covering the outer circle is switched to a TexCoordRemapper. break; case HuginBase::PanoramaOptions::CYLINDRICAL: case HuginBase::PanoramaOptions::EQUIRECTANGULAR: @@ -295,7 +305,6 @@ unsigned int x, y, row_size, depth; tree.GetPosition(node_num, x, y, row_size, depth); tree.GetInputCoordinates(node_num, tex_coords); - // TODO fix for edges where subdivision decreases TreeNode *node = &tree.nodes[node_num], *parent = (depth) ? &tree.nodes[tree.GetParentId(x, y, row_size, depth)] : 0, @@ -303,7 +312,7 @@ &tree.nodes[tree.GetIndex(x-1, y, row_size, depth)] : 0, *top = (y % 2) ? &tree.nodes[tree.GetIndex(x, y-1, row_size, depth)] : 0; - + bool valid[2][2]; for (unsigned short int i = 0; i < 2; i++) { for (unsigned short int j = 0; j < 2; j++) @@ -311,26 +320,30 @@ if (depth == 0) { // the top level has no parent, so we must calculate all points - transform.transformImgCoord(node->verts[i][j][0], - node->verts[i][j][1], - tex_coords[i][j][0] * width, - tex_coords[i][j][1] * height); + valid[i][j] = + transform.transformImgCoord(node->verts[i][j][0], + node->verts[i][j][1], + tex_coords[i][j][0] * width, + tex_coords[i][j][1] * height); } else - // Lookup where the point in the tree so far. If this is the first - // occurence of this point, we'll calculate the value. + // Look up where the point in the tree so far. If this is the first + // occurrence of this point, we'll calculate the value. if (i == x %2 && j == y%2 && depth) { // extract a corner from the parent. node->verts[i][j][0] = parent->verts[i][j][0]; node->verts[i][j][1] = parent->verts[i][j][1]; + valid[i][j] = !(parent->flags & (transform_fail_flag << (j*2 +i))); } else if (x % 2 && !i) { // copy from the left node->verts[0][j][0] = left->verts[1][j][0]; node->verts[0][j][1] = left->verts[1][j][1]; + valid[i][j] = !(left->flags & (transform_fail_flag << (j *2 + 1))); } else if (y % 2 && !j) { // copy from the top node->verts[i][0][0] = top->verts[i][1][0]; node->verts[i][0][1] = top->verts[i][1][1]; + valid[i][j] = !(top->flags & (transform_fail_flag << (2 + i))); } else { // We can't find it easily, try a more expensive search. // this will linearly interpolate along the edges where the @@ -342,10 +355,11 @@ node->verts[i][j][1])) { // We can't find it, so calculate it: - transform.transformImgCoord(node->verts[i][j][0], - node->verts[i][j][1], - tex_coords[i][j][0] * width, - tex_coords[i][j][1] * height); + valid[i][j] = + transform.transformImgCoord(node->verts[i][j][0], + node->verts[i][j][1], + tex_coords[i][j][0] * width, + tex_coords[i][j][1] * height); // If the face results from a patch subdivision (for // aligning a subdivided face, otherwise it need not exist), // use the midpoint of the parent's vertices instead of @@ -362,9 +376,9 @@ // we should be on the side away from the subdivison // (+ve y). && j - // If we are split in y we can use the middle + // If we are alao split in y we can use the middle // node to provide more detail. - && !(parent->flags & split_flag_y && (y % 2))) + && !((parent->flags & split_flag_y) && !(y % 2))) { node->verts[i][1][0] = (parent->verts[0][1][0] + parent->verts[1][1][0]) / 2.0; @@ -376,13 +390,16 @@ && (parent->flags & patch_flag_y) && ((j + y) % 2) && i - && !((x % 2) && parent->flags & split_flag_x)) + && !((parent->flags & split_flag_x) && !(x % 2))) { - node->verts[i][1][0] = (parent->verts[1][0][0] + /*node->verts[1][j][0] = (parent->verts[1][0][0] + parent->verts[1][1][0]) / 2.0; - node->verts[i][1][1] = (parent->verts[1][0][1] - + parent->verts[1][1][1]) / 2.0; + node->verts[1][j][1] = (parent->verts[1][0][1] + + parent->verts[1][1][1]) / 2.0;*/ } + } else { + // we managed to find it from data already known. + valid[i][j] = true; } } //std::cout << "(" << tex_coords[i][j][0] << ", " << tex_coords[i][j][1] << ") |-> (" << node->verts[i][j][0] << ", " << node->verts[i][j][1] << ")\n"; @@ -392,6 +409,18 @@ // now for the recursion // which directions should we divide in? TestSubdivide(node_num); + // add the flags for invlaid transormations + for (unsigned int i = 0; i < 2; i++) + { + for (unsigned int j = 0; j < 2; j++) + { + if (!valid[i][j]) + { + node->flags |= transform_fail_flag << (j * 2 + i); + } + } + } + // if the face should be split, now recurse to the child nodes. if (node->flags & (split_flag_x | split_flag_y)) { // we will split at least one way. @@ -437,7 +466,6 @@ void VertexCoordRemapper::TestSubdivide(unsigned int node_id) { - // FIXME with circular cropping we might not subdivide enough this way. TreeNode *node = &tree.nodes[node_id]; unsigned int x, y, row_size, depth; tree.GetPosition(node_id, x, y, row_size, depth); @@ -568,72 +596,9 @@ switch (output_projection) { case HuginBase::PanoramaOptions::RECTILINEAR: - // 60 degrees off centre in any direction? - // FIXME? - /*if ( node->verts[0][0][0] < lower_bound - || node->verts[0][0][0] > upper_bound - || node->verts[1][0][0] < lower_bound - || node->verts[1][0][0] > upper_bound - || node->verts[0][1][0] < lower_bound - || node->verts[0][1][0] > upper_bound - || node->verts[1][1][0] < lower_bound - || node->verts[1][1][0] > upper_bound - || node->verts[0][0][1] < lower_bound_h - || node->verts[0][0][1] > upper_bound_h - || node->verts[1][0][1] < lower_bound_h - || node->verts[1][0][1] > upper_bound_h - || node->verts[0][1][1] < lower_bound_h - || node->verts[0][1][1] > upper_bound_h - || node->verts[1][1][1] < lower_bound_h - || node->verts[1][1][1] > upper_bound_h) - { - noncontinuous = true; - // Divide the vertices into two sets based on angle. - // angles within 90 degrees either side of the 1st one are - // in one set, the rest in the other. - double angle_1 = atan2(node->verts[0][0][1], node->verts[0][0][0]), - min_angle = angle_1 - (M_PI / 2.0), - max_angle = angle_1 + (M_PI / 2.0), - angle_2 = atan2(node->verts[0][1][1], node->verts[0][1][0]), - angle_3 = atan2(node->verts[1][0][1], node->verts[1][0][0]), - angle_4 = atan2(node->verts[1][1][1], node->verts[1][1][0]); - if (min_angle < -M_PI) - { - // we need to adjust the angle limits as we underflowed - // the range used for the angles. - double angle_store = max_angle; - max_angle = 2 * M_PI + min_angle; - min_angle = angle_store; - // ...now we are working the wrong way around. - // If all the side flags were toggled, we would get the - // same faces in the opposite order, so we just do this: - flags |= vertex_side_flag_start; - } - else if (max_angle > M_PI) - { - // we need to adjust the angle limits as we overflowed - // the range used for the angles. - double angle_store = min_angle; - min_angle = max_angle - 2 * M_PI; - max_angle = angle_store; - // ...now we are working the wrong way around. - // If all the side flags were toggled, we would get the - // same faces in the opposite order, so we just do this: - flags |= vertex_side_flag_start; - } - if (angle_2 < min_angle || angle_2 > max_angle) - { - flags |= vertex_side_flag_start * 2; - } - if (angle_3 < min_angle || angle_3 > max_angle) - { - flags |= vertex_side_flag_start * 4; - } - if (angle_4 < min_angle || angle_4 > max_angle) - { - flags |= vertex_side_flag_start * 8; - } - }*/ + // we don't need faces to cross from one side to another. Faces + // all / partially 'behind the viewer' are skipped because the + // vertices behind the viewer are marked. break; case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE: case HuginBase::PanoramaOptions::STEREOGRAPHIC: @@ -758,8 +723,38 @@ node->flags = flags; // check if the faces to the left are subdivided at a higher level - if (x && !(flags & split_flag_y) && depth < max_depth) + if (x && !(flags & split_flag_y) && (depth < max_depth)) { + // get the potentially more subdivided version + double dest_x, dest_y; + unsigned int subdiv_node; + subdiv_node = tree.GetTransform(x * 2, y * 2 + 1, + depth * 2, + x * 2, y * 2, dest_x, dest_y); + if (subdiv_node > node_id) + { + // we should have a more subdivided node on the left. + // mark it for patching up to line up with it. + node->flags |= split_flag_y | patch_flag_y; + } + } + if (y && !(flags & split_flag_x) && (depth < max_depth)) + { + // get the potentially more subdivided version + double dest_x, dest_y; + unsigned int subdiv_node; + subdiv_node = tree.GetTransform(x * 2 + 1, y * 2, + depth * 2, + x * 2, y * 2, dest_x, dest_y); + if (subdiv_node > node_id) + { + // we should have a more subdivided node on the left. + // mark it for patching up to line up with it. + node->flags |= split_flag_x | patch_flag_x; + } + } + /*if (x && !(flags & split_flag_y) && depth < max_depth) + { // scan back up the tree until we get something with a child node on the // left not containing this node. unsigned int nid = node_id, depth_c = 0.0; @@ -775,7 +770,7 @@ // take the child not containing the node we are testing x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; // we'll need to deduce the location in y again. - if (y_split && y2 != y >> (depth - depth2)) y2++; + if (y_split && (y2 != (y >> (depth - depth2)))) y2++; nid = tree.GetIndex(x2, y2, row_size2, depth2); if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; // now we go right child until we get to the same depth, if there is @@ -788,7 +783,7 @@ if ((tree.nodes[nid].flags & split_flag_x)) x2++; // there will be a split in y, so work out which child gets us // where we want to be: - if (y2 != y >> (depth - depth2)) y2++; + if (y2 != (y >> (depth - depth2))) y2++; nid = tree.GetIndex(x2, y2, row_size2, depth2); if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; } @@ -818,7 +813,7 @@ // take the child not containing the node we are testing x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; // we'll need to deduce the location in x again. - if (x_split && x2 != x >> (depth - depth2)) x2++; + if (x_split && (x2 != (x >> (depth - depth2)))) x2++; nid = tree.GetIndex(x2, y2, row_size2, depth2); if (!(tree.nodes[nid].flags & split_flag_x)) x_split = false; // now we take the downward child until we get to the same depth, if @@ -841,7 +836,7 @@ // we want to split just to line up with the other subdivision. node->flags |= split_flag_x | patch_flag_x; } - } + }*/ } void VertexCoordRemapper::SetLengthAndAngle(TreeNode *node) @@ -1067,7 +1062,7 @@ return cur_tree_node; } -bool VertexCoordRemapper::Tree::GetTransform(unsigned int src_x, unsigned int src_y, +unsigned int VertexCoordRemapper::Tree::GetTransform(unsigned int src_x, unsigned int src_y, unsigned int max_depth, unsigned int stop_x, unsigned int stop_y, double &dest_x, double &dest_y) @@ -1108,10 +1103,13 @@ } // we want to stop if we have got a node at least as high as the // requested stopping node. Anything at a higher depth is after it. - if (depth > max_depth) return false; + if (depth > max_depth) return 0; node_id = GetIndex(no_x, no_y, row_size, depth); } - if (depth == max_depth && no_x >= stop_x && no_y >= stop_y) return false; + if (depth == max_depth && no_x >= stop_x && no_y >= stop_y) return 0; + // if any of the vertices we are want to use are invalid (e.g. behind the + // viewer in a rectilinear projection) we don't want to risk using them: + if (nodes[node_id].flags & (transform_fail_flag * 15)) return 0; // linearly interpolate the node's corners. // most of the time we only use factors of 0 and 1, we don't want to make // points up except when trying to connect a point on a highly subdivided @@ -1136,6 +1134,6 @@ + xf * nodes[node_id].verts[1][1][1]; dest_x = top_x * (1.0 - yf) + bottom_x * yf; dest_y = top_y * (1.0 - yf) + bottom_y* yf; - return true; + return node_id; } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h 2008-07-20 02:10:45 UTC (rev 3212) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.h 2008-07-21 21:16:43 UTC (rev 3213) @@ -159,13 +159,14 @@ void GetInputCoordinates(unsigned int node_num, double coords[2][2][2]); // tries to find a transformed coordinate in the tree that would have - // been written before stop. If there are none, return false, otherwise - // set dest_x and dest_y. This takes into account where the subdivision - // has stopped and performs linear interpolation in that case. - bool GetTransform(unsigned int src_x, unsigned int src_y, - unsigned int depth, - unsigned int stop_x, unsigned int stop_y, - double &dest_x, double &dest_y); + // been written before stop. If there are none, return 0, otherwise + // set dest_x and dest_y and return the number of the node it used to + // work that out. This takes into account where the subdivision has + // stopped and performs linear interpolation in that case. + unsigned int GetTransform(unsigned int src_x, unsigned int src_y, + unsigned int depth, + unsigned int stop_x, unsigned int stop_y, + double &dest_x, double &dest_y); // Array of as many nodes necessary to store a full tree with subdivions // up to max_depth (defined in VertexCoordRemapper.cpp) times. TreeNode nodes[1+4+16+64+256+1024+4096]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-22 03:37:06
|
Revision: 3214 http://hugin.svn.sourceforge.net/hugin/?rev=3214&view=rev Author: jlegg Date: 2008-07-22 03:37:04 +0000 (Tue, 22 Jul 2008) Log Message: ----------- Implemented PreviewTool and PreviewToolHelper, although they are not intergrated or tested. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-07-21 21:16:43 UTC (rev 3213) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-07-22 03:37:04 UTC (rev 3214) @@ -31,7 +31,7 @@ LocalizedFileTipProvider.cpp wxPanoCommand.cpp AssistantPanel.cpp HFOVDialog.cpp TextureManager.cpp MeshRemapper.cpp VertexCoordRemapper.cpp TexCoordRemapper.cpp ChoosyRemapper.cpp MeshManager.cpp ViewState.cpp -OutputProjectionInfo.cpp) +OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp) IF(APPLE) if (MAC_SELF_CONTAINED_BUNDLE) Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp 2008-07-22 03:37:04 UTC (rev 3214) @@ -0,0 +1,29 @@ +// -*- c-basic-offset: 4 -*- + +/** @file PreviewTool.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "PreviewTool.h" + +PreviewTool::PreviewTool(PreviewToolHelper *helper_in) +{ + helper = helper_in; +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-07-21 21:16:43 UTC (rev 3213) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-07-22 03:37:04 UTC (rev 3214) @@ -50,10 +50,11 @@ virtual void AfterDrawImagesEvent() {} // if the tool uses this event to draw the image itself, return false. // otherwise, return true and the image will be drawn normally. - // Use this, for example, to the in-order drawing - virtual bool BeforeDrawImageEvent() {} + // Use this, for example, to alter the in-order drawing + virtual bool BeforeDrawImageEvent(unsigned int image) {return true;} // called just after the image was drawn normally. - virtual void AfterDrawImageEvent() {} + virtual void AfterDrawImageEvent(unsigned int image) {} protected: PreviewToolHelper *helper; -} +}; + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-21 21:16:43 UTC (rev 3213) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-22 03:37:04 UTC (rev 3214) @@ -29,15 +29,304 @@ { pano = pano_in; view_state = view_state_in; + mouse_button_notified_tool = 0; + keypress_notified_tool = 0; + images_under_mouse_current = false; } PreviewToolHelper::~PreviewToolHelper() { } -std::vector<PreviewTool> ActivateTool::(PreviewTool *tool) +std::set<PreviewTool *> PreviewToolHelper::ActivateTool(PreviewTool *tool) { tools_deactivated.clear(); - tool.Activate(); + tool->Activate(); return tools_deactivated; } + +void PreviewToolHelper::DeactivateTool(PreviewTool *tool) +{ + tools_deactivated.insert(tool); + // To deactivate it we need to give up all of its notifications. + RemoveTool(tool, &mouse_button_notified_tool); + RemoveTool(tool, &keypress_notified_tool); + RemoveTool(tool, &mouse_move_notified_tools); + RemoveTool(tool, &draw_under_notified_tools); + RemoveTool(tool, &draw_over_notified_tools); + RemoveTool(tool, &image_draw_begin_tools); + RemoveTool(tool, &image_draw_end_tools); +} + +void PreviewToolHelper::MouseMoved(unsigned int x, unsigned int y) +{ + // work out where the pointer is in the panorama. + vigra::Rect2D visible = view_state->GetVisibleArea(); + mouse_x = (double) x * view_state->GetScale() + (double) visible.left(); + mouse_y = (double) y * view_state->GetScale() + (double) visible.top(); + // now tell tools that want notification. + std::set<PreviewTool *>::iterator iterator; + for (iterator = mouse_move_notified_tools.begin(); + iterator != mouse_move_notified_tools.end(); iterator++) + { + (*iterator)->MouseMoveEvent(mouse_x, mouse_y); + } + // If the mouse has moved, then we don't know what is underneath it anoymore + images_under_mouse_current = false; +} + +void PreviewToolHelper::MouseButtonEvent(unsigned short int button, bool pressed) +{ + // if there is a tool monitoring mouse button presses, notify it + if (mouse_button_notified_tool) + { + mouse_button_notified_tool->MouseButtonEvent(button, pressed); + } +} + +void PreviewToolHelper::KeypressEvent(int keycode, bool pressed) +{ + if (keypress_notified_tool) + { + keypress_notified_tool->KeypressEvent(keycode, pressed); + } +} + +void PreviewToolHelper::BeforeDrawImages() +{ + // let all tools that want to draw under the images do so. + std::set<PreviewTool *>::iterator iterator; + for (iterator = draw_under_notified_tools.begin(); + iterator != draw_under_notified_tools.end(); iterator++) + { + (*iterator)->BeforeDrawImagesEvent(); + } + // Since we are drawing a new frame, lets assume something has changed. + images_under_mouse_current = false; +} + +void PreviewToolHelper::AfterDrawImages() +{ + // let all tools that want to draw on top of the images do so. + std::set<PreviewTool *>::iterator iterator; + for (iterator = draw_over_notified_tools.begin(); + iterator != draw_over_notified_tools.end(); iterator++) + { + (*iterator)->AfterDrawImagesEvent(); + } +} + +bool PreviewToolHelper::BeforeDrawImageNumber(unsigned int image) +{ + if (image_draw_begin_tools.size() > image) + { + if (image_draw_begin_tools[image]) + { + return image_draw_begin_tools[image]->BeforeDrawImageEvent(image); + } + } + return true; +} + +void PreviewToolHelper::AfterDrawImageNumber(unsigned int image) +{ + if (image_draw_end_tools.size() > image) + { + if (image_draw_end_tools[image]) + { + image_draw_end_tools[image]->AfterDrawImageEvent(image); + } + } +} + +std::set<unsigned int> PreviewToolHelper::GetImageNumbersUnderMouse() +{ + if (!images_under_mouse_current) + { + UpdateImagesUnderMouse(); + } + return images_under_mouse; +} + +std::pair<double, double> PreviewToolHelper::GetMousePosition() +{ + return std::pair<unsigned int, unsigned int>(mouse_x, mouse_y); +} + +ViewState *PreviewToolHelper::GetViewStatePtr() +{ + return view_state; +} + +HuginBase::Panorama *PreviewToolHelper::GetPanoramaPtr() +{ + return pano; +} + +void PreviewToolHelper::NotifyMe(Event event, PreviewTool *tool) +{ + switch (event) + { + case MOUSE_MOVE: + AddTool(tool, &mouse_move_notified_tools); + break; + case MOUSE_PRESS: + AddTool(tool, &mouse_button_notified_tool); + break; + case KEY_PRESS: + AddTool(tool, &keypress_notified_tool); + break; + case DRAW_UNDER_IMAGES: + AddTool(tool, &draw_under_notified_tools); + break; + case DRAW_OVER_IMAGES: + AddTool(tool, &draw_over_notified_tools); + break; + } +} + +void PreviewToolHelper::NotifyMeBeforeDrawing(unsigned int image_nr, + PreviewTool *tool) +{ + AddTool(tool, &image_draw_begin_tools, image_nr); +} + +void PreviewToolHelper::NotifyMeAfterDrawing(unsigned int image_nr, + PreviewTool *tool) +{ + AddTool(tool, &image_draw_end_tools, image_nr); +} + +void PreviewToolHelper::DoNotNotifyMe(Event event, PreviewTool *tool) +{ + // TODO we should probably check that the tools have the notification they + // are trying to give up, as misbehaving tools could break another tool. + switch (event) + { + case MOUSE_MOVE: + RemoveTool(tool, &mouse_move_notified_tools); + break; + case MOUSE_PRESS: + RemoveTool(tool, &mouse_button_notified_tool); + break; + case KEY_PRESS: + RemoveTool(tool, &keypress_notified_tool); + break; + case DRAW_UNDER_IMAGES: + RemoveTool(tool, &draw_under_notified_tools); + break; + case DRAW_OVER_IMAGES: + RemoveTool(tool, &draw_over_notified_tools); + break; + } +} + +void PreviewToolHelper::DoNotNotifyMeBeforeDrawing(unsigned int image_nr, + PreviewTool *tool) +{ + RemoveTool(tool, &image_draw_begin_tools, image_nr); +} + +void PreviewToolHelper::DoNotNotifyMeAfterDrawing(unsigned int image_nr, + PreviewTool *tool) +{ + RemoveTool(tool, &image_draw_end_tools, image_nr); +} + +// These functions remove tools from various things that keep pointers to them +// so that they can be notified. They are called when we don't want to notify +// them anymore. + +void PreviewToolHelper::RemoveTool(PreviewTool *tool, PreviewTool **single) +{ + if (*single == tool) + { + *single = 0; + } +} + +void PreviewToolHelper::RemoveTool(PreviewTool *tool, + std::set<PreviewTool *> *set) +{ + std::set<PreviewTool *>::iterator iterator = set->find(tool); + if (iterator != set->end()) + { + set->erase(iterator); + } +} + +void PreviewToolHelper::RemoveTool(PreviewTool *tool, + std::vector<PreviewTool *> *vector) +{ + // check every item for presence. + for (unsigned int image = 0; image < vector->size(); image++) + { + if ((*vector)[image] == tool) + { + (*vector)[image] = 0; + } + } +} + +void PreviewToolHelper::RemoveTool(PreviewTool *tool, + std::vector<PreviewTool *> *vector, + unsigned int index) +{ + if ((*vector)[index] == tool) + { + (*vector)[index] = 0; + } +} + +void PreviewToolHelper::AddTool(PreviewTool *tool, PreviewTool **single) +{ + if (*single != 0) + { + DeactivateTool(*single); + } + *single = tool; +} + +void PreviewToolHelper::AddTool(PreviewTool *tool, std::set<PreviewTool *> *set) +{ + set->insert(tool); +} + +void PreviewToolHelper::AddTool(PreviewTool *tool, + std::vector<PreviewTool *> *vector, + unsigned int index) +{ + if (vector->size() < index) + { + // increase the size of the vector to handle enough elements for index + // to exist + vector->resize(index + 1, 0); + } + else if ((*vector)[index]) + { + // if a tool already was doing this, deactivate it. + DeactivateTool((*vector)[index]); + }; + (*vector)[index] = tool; +} + + +void PreviewToolHelper::UpdateImagesUnderMouse() +{ + images_under_mouse.clear(); + unsigned int num_images = pano->getNrOfImages(); + for (unsigned int image_index = 0; image_index < num_images; image_index++) + { + HuginBase::PTools::Transform transform; + transform.createTransform(*view_state->GetSrcImage(image_index), + *view_state->GetOptions()); + double image_x, image_y; + transform.transformImgCoord(image_x, image_y, mouse_x, mouse_y); + if (view_state->GetSrcImage(image_index)->isInside( + vigra::Point2D(int(image_x), int (image_y)))) + { + images_under_mouse.insert(image_index); + } + } + images_under_mouse_current = true; +} Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-21 21:16:43 UTC (rev 3213) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-22 03:37:04 UTC (rev 3214) @@ -51,10 +51,12 @@ #define _PREVIEWTOOLHELPER_H #include <wx/defs.h> +#include <set> #include <vector> -#include <string> +#include <utility> #include "ViewState.h" +#include <panodata/Panorama.h> class PreviewTool; @@ -64,19 +66,15 @@ enum Event { MOUSE_MOVE, MOUSE_PRESS, KEY_PRESS, - REDRAW_REQURIED, DRAW_UNDER_IMAGES, DRAW_OVER_IMAGES, - MESH_CHANGE, - // each image has it's own event numeration, starting with this one: - DRAW_IMAGE_0 + DRAW_UNDER_IMAGES, DRAW_OVER_IMAGES, }; PreviewToolHelper(HuginBase::Panorama *pano, ViewState *view_state); ~PreviewToolHelper(); // working with tools - void AddTool(PreviewTool *tool); // Activate a tool, the tool will then request notifications it needs. // Then return a list of tools that had to be dactivated to comply. - std::vector<*PreviewTool> ActivateTool(PreviewTool *tool); + std::set<PreviewTool*> ActivateTool(PreviewTool *tool); // deactivate a tool: remove all it's notifications. void DeactivateTool(PreviewTool *tool); @@ -90,24 +88,52 @@ void AfterDrawImages(); // Return true if we want it drawn, return false and draw the image as the // tools specify otherwise. - bool BeforeDrawImageNumber(); - void AfterDrawImageNumber(); + bool BeforeDrawImageNumber(unsigned int image); + void AfterDrawImageNumber(unsigned int image); // Get information - std::vector<unsigned int> GetImageNumbersUnderMouse(); - pair<unsigned int, unsigned int> GetMousePosition(); + std::set<unsigned int> GetImageNumbersUnderMouse(); + std::pair<double, double> GetMousePosition(); ViewState *GetViewStatePtr(); HuginBase::Panorama *GetPanoramaPtr(); // Setting up notifications - NotifyMe(Event *event, Tool *tool); - DoNotNotifyMe(Event *event, PreviewTool *tool); - + void NotifyMe(Event event, PreviewTool *tool); + void NotifyMeBeforeDrawing(unsigned int image_nr, PreviewTool *tool); + void NotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); + void DoNotNotifyMe(Event event, PreviewTool *tool); + void DoNotNotifyMeBeforeDrawing(unsigned int image_nr, PreviewTool *tool); + void DoNotNotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); private: - std::vector<*PreviewTool> tools_deactivated; + std::set<PreviewTool *> tools_deactivated; HuginBase::Panorama *pano; ViewState *view_state; - unsigned int mouse_x, mouse_y; -} + double mouse_x, mouse_y; + + // What tools are notified of what events. + std::set<PreviewTool *> mouse_move_notified_tools; + PreviewTool * mouse_button_notified_tool; + PreviewTool * keypress_notified_tool; + std::set<PreviewTool *> draw_under_notified_tools; + std::set<PreviewTool *> draw_over_notified_tools; + // these are vectors: the index is the image that a single tool uses. + std::vector<PreviewTool *> image_draw_begin_tools; + std::vector<PreviewTool *> image_draw_end_tools; + // stop notifying the given tool of an event. + void RemoveTool(PreviewTool *tool, PreviewTool **single); + void RemoveTool(PreviewTool *tool, std::set<PreviewTool *> *set); + void RemoveTool(PreviewTool *tool, std::vector<PreviewTool *> *vector); + void RemoveTool(PreviewTool *tool, std::vector<PreviewTool *> *vector, + unsigned int index); + // set the tool up for notification, deactivating any tools in the way. + void AddTool(PreviewTool *tool, PreviewTool **single); + void AddTool(PreviewTool *tool, std::set<PreviewTool *> *set); + void AddTool(PreviewTool *tool, std::vector<PreviewTool *> *vector, + unsigned int index); + // is the set of images under the mouse up to date? + bool images_under_mouse_current; + std::set<unsigned int> images_under_mouse; + void UpdateImagesUnderMouse(); +}; #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-23 02:54:32
|
Revision: 3216 http://hugin.svn.sourceforge.net/hugin/?rev=3216&view=rev Author: jlegg Date: 2008-07-23 02:54:29 +0000 (Wed, 23 Jul 2008) Log Message: ----------- More things for interactive preview tools. Implemented a shiny new cropping tool. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-07-23 02:54:29 UTC (rev 3216) @@ -31,7 +31,8 @@ LocalizedFileTipProvider.cpp wxPanoCommand.cpp AssistantPanel.cpp HFOVDialog.cpp TextureManager.cpp MeshRemapper.cpp VertexCoordRemapper.cpp TexCoordRemapper.cpp ChoosyRemapper.cpp MeshManager.cpp ViewState.cpp -OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp) +OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp +PreviewCropTool.cpp) IF(APPLE) if (MAC_SELF_CONTAINED_BUNDLE) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-23 02:54:29 UTC (rev 3216) @@ -55,6 +55,9 @@ #endif } +#include "PreviewToolHelper.h" +#include "PreviewCropTool.h" + using namespace utils; // a random id, hope this doesn't break something.. @@ -77,10 +80,12 @@ EVT_TOOL(XRCID("preview_center_tool"), GLPreviewFrame::OnCenterHorizontally) EVT_TOOL(XRCID("preview_fit_pano_tool"), GLPreviewFrame::OnFitPano) EVT_TOOL(XRCID("preview_straighten_pano_tool"), GLPreviewFrame::OnStraighten) + EVT_TOOL(XRCID("preview_num_transform"), GLPreviewFrame::OnNumTransform) EVT_TOOL(XRCID("preview_show_all_tool"), GLPreviewFrame::OnShowAll) EVT_TOOL(XRCID("preview_show_none_tool"), GLPreviewFrame::OnShowNone) - EVT_TOOL(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric) - EVT_TOOL(XRCID("preview_num_transform"), GLPreviewFrame::OnNumTransform) + EVT_TOOL(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric) + EVT_TOOL(XRCID("preview_crop_tool"), GLPreviewFrame::OnCrop) + EVT_TEXT_ENTER( -1 , GLPreviewFrame::OnTextCtrlChanged) EVT_BUTTON(ID_EXPOSURE_DEFAULT, GLPreviewFrame::OnDefaultExposure) @@ -140,7 +145,7 @@ // create our Viewer int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0}; - m_GLViewer = new GLViewer(this, pano, args); + m_GLViewer = new GLViewer(this, pano, args, this); flexSizer->Add(m_GLViewer, 1, // not vertically stretchable @@ -947,3 +952,26 @@ m_GLViewer->SetPhotometricCorrect(e.IsChecked()); } +void GLPreviewFrame::MakeTools(PreviewToolHelper *helper_in) +{ + // create the tool objects. + // we delay this until we have an OpenGL context so that they are free to + // create texture objects and display lists before they are used. + helper = helper_in; + crop_tool = new PreviewCropTool(helper); +} + +void GLPreviewFrame::OnCrop(wxCommandEvent & e) +{ + // turn on or off the crop tool when it's button is pressed. + if (e.IsChecked()) + { + helper->ActivateTool(crop_tool); + } else { + helper->DeactivateTool(crop_tool); + } + // the tool draws some extra guides that need to be shown when starting or + // covered up when done; therefore update the display. + m_GLViewer->Refresh(); +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-07-23 02:54:29 UTC (rev 3216) @@ -27,6 +27,8 @@ class wxToggleButton; class wxCheckBox; class GLViewer; +class PreviewToolHelper; +class PreviewCropTool; /** The OpenGL preview frame * @@ -51,6 +53,8 @@ void panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet &changed); void updateProgressDisplay(); + + void MakeTools(PreviewToolHelper * helper); protected: void OnClose(wxCloseEvent& e); @@ -61,6 +65,7 @@ void OnShowAll(wxCommandEvent & e); void OnShowNone(wxCommandEvent & e); void OnPhotometric(wxCommandEvent & e); + void OnCrop(wxCommandEvent & e); void OnNumTransform(wxCommandEvent & e); void OnChangeFOV(wxScrollEvent & e); void OnTrackChangeFOV(wxScrollEvent & e); @@ -111,6 +116,10 @@ #endif DECLARE_EVENT_TABLE() + + // tools + PreviewToolHelper *helper; + PreviewCropTool *crop_tool; }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-23 02:54:29 UTC (rev 3216) @@ -46,22 +46,25 @@ #include "MeshManager.h" #include "ViewState.h" #include "GLRenderer.h" -#include "panodata/PanoramaOptions.h" +#include "PreviewToolHelper.h" +#include <panodata/PanoramaOptions.h> GLRenderer::GLRenderer(PT::Panorama *pano, TextureManager *tex_man, - MeshManager *mesh_man, ViewState *view_state) + MeshManager *mesh_man, ViewState *view_state, + PreviewToolHelper *tool_helper) { m_pano = pano; m_tex_man = tex_man; m_mesh_man = mesh_man; - m_view_state =view_state; + m_view_state = view_state; + m_tool_helper = tool_helper; } GLRenderer::~GLRenderer() { } -float GLRenderer::Resize(int in_width, int in_height) +std::pair<int, int> GLRenderer::Resize(int in_width, int in_height) { width = in_width; height = in_height; @@ -70,11 +73,11 @@ HuginBase::PanoramaOptions *options = m_view_state->GetOptions(); width_o = options->getWidth(); height_o = options->getHeight(); - float aspect_screen = float(width) / float (height), + double aspect_screen = double(width) / double (height), aspect_pano = width_o / height_o; glMatrixMode(GL_PROJECTION); glLoadIdentity(); - float scale; + double scale; if (aspect_screen < aspect_pano) { // the panorama is wider than the screen @@ -83,8 +86,8 @@ // the screen is wider than the panorama scale = height_o / height; } - float x_offs = (scale * float(width) - width_o) / 2.0, - y_offs = (scale * float(height) - height_o) / 2.0; + double x_offs = (scale * double(width) - width_o) / 2.0, + y_offs = (scale * double(height) - height_o) / 2.0; // set up the projection, so we can use panorama coordinates. glOrtho(-x_offs, width * scale - x_offs, height * scale - y_offs, -y_offs, @@ -97,7 +100,8 @@ // TODO add support for zooming and panning. m_view_state->SetVisibleArea(vigra::Rect2D(0, 0, options->getWidth(), options->getHeight())); - return 1.0 / scale; + m_view_state->SetScale(1.0 / scale); + return std::pair<int, int>(int (x_offs / scale), int (y_offs / scale)); } void GLRenderer::SetBackground(unsigned char red, unsigned char green, unsigned char blue) @@ -107,9 +111,9 @@ void GLRenderer::Redraw() { - // draw the box around the panorma in black, with a white background. glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); + // draw the box around the panorma in black, with some background colour. glDisable(GL_TEXTURE_2D); glColor3f(0.0, 0.0, 0.0); glBegin(GL_QUADS); @@ -119,9 +123,11 @@ glVertex2f(0.0, height_o); glEnd(); glColor3f(1.0, 1.0, 1.0); + // draw things under the preview images + m_tool_helper->BeforeDrawImages(); // draw each active image. int imgs = m_pano->getNrOfImages(); - // offset by a pixel + // offset by a half a pixel glPushMatrix(); glTranslatef(0.5, 0.5, 0.0); glEnable(GL_TEXTURE_2D); @@ -131,10 +137,14 @@ { if (m_pano->getImage(img).getOptions().active) { + m_tool_helper->BeforeDrawImageNumber(img); m_tex_man->DrawImage(img, m_mesh_man->GetDisplayList(img)); + m_tool_helper->AfterDrawImageNumber(img); } } m_tex_man->End(); + // drawn things after the active image. + m_tool_helper->AfterDrawImages(); glDisable(GL_TEXTURE_2D); glPopMatrix(); // darken the cropped out range Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-07-23 02:54:29 UTC (rev 3216) @@ -36,21 +36,26 @@ #define DEBUG_HEADER "" #include <base_wx/ImageCache.h> #include <vigra_ext/ROIImage.h> +#include <utility> +class PreviewToolHelper; + class GLRenderer { public: /** ctor. */ GLRenderer(PT::Panorama * pano, TextureManager *tex_man, - MeshManager *mesh_man, ViewState *veiw_state); + MeshManager *mesh_man, ViewState *veiw_state, + PreviewToolHelper *tool_helper); /** dtor. */ virtual ~GLRenderer(); // resize the viewport, because the window's dimensions have changed. - // returns the nnumber of screen pixels for a panorama pixel. - float Resize(int width, int height); + // returns the number of screen pixels until the start of the panorma, + // both horizontally and vertically. + std::pair<int, int> Resize(int width, int height); // void panoramaChanged(PT::Panorama &pano); // void panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet & imgNr); void Redraw(); @@ -61,6 +66,7 @@ TextureManager * m_tex_man; MeshManager * m_mesh_man; ViewState * m_view_state; + PreviewToolHelper *m_tool_helper; int width, height; }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-07-23 02:54:29 UTC (rev 3216) @@ -22,6 +22,8 @@ #include <config.h> #include <GL/glew.h> #include <wx/settings.h> +#include <wx/dcclient.h> +#include <wx/event.h> #include "panoinc.h" @@ -29,15 +31,23 @@ #include "GLRenderer.h" #include "TextureManager.h" #include "MeshManager.h" +#include "PreviewToolHelper.h" +#include "GLPreviewFrame.h" - BEGIN_EVENT_TABLE(GLViewer, wxGLCanvas) EVT_PAINT (GLViewer::RedrawE) EVT_SIZE (GLViewer::Resized) + // mouse motion + EVT_MOTION (GLViewer::MouseMotion) + // mouse buttons + EVT_LEFT_DOWN (GLViewer::LeftDown) + EVT_LEFT_UP (GLViewer::LeftUp) + EVT_RIGHT_DOWN (GLViewer::RightDown) + EVT_RIGHT_UP (GLViewer::RightUp) END_EVENT_TABLE() -GLViewer::GLViewer(wxFrame* parent, PT::Panorama &pano, int args[]) : +GLViewer::GLViewer(wxFrame* parent, PT::Panorama &pano, int args[], GLPreviewFrame *frame_in) : wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, 0, wxT("GLPreviewCanvas"), wxNullPalette) { @@ -48,6 +58,8 @@ m_pano = &pano; + frame = frame_in; + started_creation = false; } @@ -56,6 +68,7 @@ delete m_glContext; if (m_renderer) { + delete m_tool_helper; delete m_renderer; delete m_tex_manager; delete m_view_state; @@ -78,18 +91,23 @@ // It appears we are setting up for the first time. // we need something to store the state of the view and control updates m_view_state = new ViewState(m_pano, RefreshWrapper, this); + // Start the tools going: + m_tool_helper = new PreviewToolHelper(m_pano, m_view_state); + frame->MakeTools(m_tool_helper); // now set the texture manager up. m_tex_manager = new TextureManager(*m_pano, m_view_state); // same for the mesh manager m_mesh_manager = new MeshManager(m_pano, m_view_state); // now make a renderer - m_renderer = new GLRenderer(m_pano, m_tex_manager, m_mesh_manager, m_view_state); + m_renderer = new GLRenderer(m_pano, m_tex_manager, m_mesh_manager, + m_view_state, m_tool_helper); // initialise the glew library. GLenum error_state = glewInit(); if (error_state != GLEW_OK) { // glewInit failed - std::cerr << "Error initlialising GLEW: " << glewGetErrorString(error_state) << ".\n"; + std::cerr << "Error initlialising GLEW: " + << glewGetErrorString(error_state) << ".\n"; } // check the openGL version if (!GLEW_VERSION_1_3) @@ -129,7 +147,7 @@ int w, h; GetClientSize(&w, &h); SetUpContext(); - m_view_state->SetScale(m_renderer->Resize(w, h)); + offset = m_renderer->Resize(w, h); }; } @@ -149,7 +167,7 @@ // resize the viewport in case the panorama dimensions have changed. int w, h; GetClientSize(&w, &h); - m_view_state->SetScale(m_renderer->Resize(w, h)); + offset = m_renderer->Resize(w, h); } m_tex_manager->CheckUpdate(); m_mesh_manager->CheckUpdate(); @@ -158,6 +176,31 @@ SwapBuffers(); // tell the view state we did all the updates and redrew. m_view_state->FinishedDraw(); - } +void GLViewer::MouseMotion(wxMouseEvent& e) +{ + m_tool_helper->MouseMoved((int) e.m_x - offset.first, + (int) e.m_y - offset.second); +} + +void GLViewer::LeftDown(wxMouseEvent& e) +{ + m_tool_helper->MouseButtonEvent(0, true); +} + +void GLViewer::LeftUp(wxMouseEvent& e) +{ + m_tool_helper->MouseButtonEvent(0, false); +} + +void GLViewer::RightDown(wxMouseEvent& e) +{ + m_tool_helper->MouseButtonEvent(1, true); +} + +void GLViewer::RightUp(wxMouseEvent& e) +{ + m_tool_helper->MouseButtonEvent(1, false); +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-07-23 02:54:29 UTC (rev 3216) @@ -24,17 +24,20 @@ #ifndef _GL_VIEWER_H #define _GL_VIEWER_H -#include "wx/glcanvas.h" #include "ViewState.h" +#include <wx/glcanvas.h> +#include <utility> class GLRenderer; class TextureManager; class MeshManager; +class PreviewToolHelper; +class GLPreviewFrame; class GLViewer: public wxGLCanvas { public: - GLViewer(wxFrame* parent, PT::Panorama &pano, int args[]); + GLViewer(wxFrame* parent, PT::Panorama &pano, int args[], GLPreviewFrame *frame); virtual ~GLViewer(); void RedrawE(wxPaintEvent& e); void Resized(wxSizeEvent& e); @@ -42,16 +45,25 @@ static void RefreshWrapper(void *obj); void SetUpContext(); void SetPhotometricCorrect(bool state); + + void MouseMotion(wxMouseEvent& e); + void LeftDown(wxMouseEvent& e); + void LeftUp(wxMouseEvent& e); + void RightDown(wxMouseEvent& e); + void RightUp(wxMouseEvent& e); + ViewState * m_view_state; protected: DECLARE_EVENT_TABLE() + PreviewToolHelper *m_tool_helper; GLRenderer *m_renderer; TextureManager *m_tex_manager; MeshManager *m_mesh_manager; wxGLContext *m_glContext; PT::Panorama * m_pano; bool started_creation; - float scale; + std::pair<int, int> offset; + GLPreviewFrame *frame; }; #endif Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-07-23 02:54:29 UTC (rev 3216) @@ -0,0 +1,220 @@ +// -*- c-basic-offset: 4 -*- + +/** @file PreviewCropTool.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "PreviewCropTool.h" +#include <config.h> +#include "panoinc_WX.h" +#include "panoinc.h" +#include "base_wx/platform.h" +#include "hugin/config_defaults.h" +#include "CommandHistory.h" +#include "wxPanoCommand.h" +#include <GL/gl.h> + +PreviewCropTool::PreviewCropTool(PreviewToolHelper *helper) + : PreviewTool(helper) +{ + +} + +void PreviewCropTool::Activate() +{ + helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); + helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); + helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); + mouse_down = false; + moving_left = false; + moving_right = false; + moving_top = false; + moving_bottom = false; +} + +void PreviewCropTool::AfterDrawImagesEvent() +{ + // draw lines for the border to crop: + // We use 1/4 of the smallest dimension as the size of an internal margin + // inside the cropping region. + // dragging a point in that margin moves the edges for the side we are on + // (so the corners move both edges) + // dragging a point in the middle moves the whole frame. + + // find the cropped region + HuginBase::PanoramaOptions *opts = helper->GetViewStatePtr()->GetOptions(); + vigra::Rect2D roi = opts->getROI(); + double width = (double) roi.width(), + height = (double) roi.height(), + margin = (width > height ? height : width) / 4.0, + o_width = opts->getSize().width(), + o_height = opts->getSize().height(); + top = (double) roi.top() + margin; + bottom = (double) roi.bottom() - margin; + left = (double) roi.left() + margin; + right = (double) roi.right() - margin; + + // actually draw the lines, invert colours under them. + glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glBegin(GL_LINES); + glVertex2d(0.0, top); glVertex2d(o_width, top); + glVertex2d(0.0, bottom); glVertex2d(o_width, bottom); + glVertex2d(left, 0.0); glVertex2d(left, o_height); + glVertex2d(right, 0.0); glVertex2d(right, o_height); + glEnd(); + // now draw boxes to indicate what dragging would do. + if (!mouse_down) + { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(1.0, 1.0, 1.0, 0.38197); + glBegin(GL_QUADS); + if (moving_left) + { + glVertex2d(roi.left(), top); glVertex2d(left, top); + glVertex2d(left, bottom); glVertex2d(roi.left(), bottom); + } + if (moving_right) + { + glVertex2d(right, top); glVertex2d(roi.right(), top); + glVertex2d(roi.right(), bottom); glVertex2d(right, bottom); + } + if (moving_top) + { + glVertex2d(right, top); glVertex2d(right, roi.top()); + glVertex2d(left, roi.top()); glVertex2d(left, top); + } + if (moving_bottom) + { + glVertex2d(right, bottom); glVertex2d(right, roi.bottom()); + glVertex2d(left, roi.bottom()); glVertex2d(left, bottom); + } + glEnd(); + } + glEnable(GL_TEXTURE_2D); + glDisable(GL_BLEND); +} + +void PreviewCropTool::MouseMoveEvent(double x, double y) +{ + if (mouse_down) + { + vigra::Rect2D roi = start_drag_options.getROI(); + if (moving_left) + { + unsigned int left_d = (int) (start_drag_x - x); + roi.setUpperLeft(vigra::Point2D(roi.left() - left_d, roi.top())); + } + if (moving_top) + { + unsigned int top_d = (int) (start_drag_y - y); + roi.setUpperLeft(vigra::Point2D(roi.left(), roi.top() - top_d)); + } + if (moving_right) + { + unsigned int right_d = (int) (start_drag_x - x); + roi.setLowerRight(vigra::Point2D(roi.right() - right_d, + roi.bottom())); + } + if (moving_bottom) + { + unsigned int bottom_d = (int) (start_drag_y - y); + roi.setLowerRight(vigra::Point2D(roi.right(), + roi.bottom() - bottom_d)); + } + opts.setROI(roi); + helper->GetViewStatePtr()->SetOptions(&opts); + helper->GetViewStatePtr()->Redraw(); + } else { + start_drag_x = x; + start_drag_y = y; + // check if the pointer moved to a region where dragging does something + // different. If so, update the display to reflect it. + // Note that since we normally only allow redraws to rerender the scene + // if the view of the panorama has changed, we have to force a redraw. + // (our moving boxes aren't known by the view_state!) + if ((x < left) != moving_left) + { + moving_left = !moving_left; + helper->GetViewStatePtr()->ForceRequireRedraw(); + } + if ((x > right) != moving_right) + { + moving_right = !moving_right; + helper->GetViewStatePtr()->ForceRequireRedraw(); + } + if ((y < top) != moving_top) + { + moving_top = !moving_top; + helper->GetViewStatePtr()->ForceRequireRedraw(); + } + if ((y > bottom) != moving_bottom) + { + moving_bottom = !moving_bottom; + helper->GetViewStatePtr()->ForceRequireRedraw(); + } + // This will only redraw again if any of the above conditionals ran. + helper->GetViewStatePtr()->Redraw(); + } +} + + +void PreviewCropTool::MouseButtonEvent(unsigned short int button, bool pressed) +{ + if (button == 0) + { + if (pressed) + { + start_drag_options = *helper->GetViewStatePtr()->GetOptions(); + opts = start_drag_options; + mouse_down = true; + moving_left = false; + moving_right = false; + moving_top = false; + moving_bottom = false; + if (start_drag_x < left) moving_left = true; + if (start_drag_x > right) moving_right = true; + if (start_drag_y < top) moving_top = true; + if (start_drag_y > bottom) moving_bottom = true; + // in the middle, move everything. + if (!(moving_left || moving_right || moving_top || moving_bottom)) + { + moving_left = true; + moving_right = true; + moving_top = true; + moving_bottom = true; + } + } else { + if (mouse_down) + { + mouse_down = false; + moving_left = false; + moving_right = false; + moving_top = false; + moving_bottom = false; + // set the new cropping region permanently. + GlobalCmdHist::getInstance().addCommand( + new PT::SetPanoOptionsCmd(*(helper->GetPanoramaPtr()), + opts)); + } + } + } +} + Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h 2008-07-23 02:54:29 UTC (rev 3216) @@ -0,0 +1,46 @@ +// -*- c-basic-offset: 4 -*- + +/** @file PreviewCropTool.h + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* this tool allows the user to change the cropping region by dragging it. + */ + +#ifndef _PREVIEWCROPTOOL_H +#define _PREVIEWCROPTOOL_H + +#include "PreviewTool.h" + +class PreviewCropTool : public PreviewTool +{ +public: + PreviewCropTool(PreviewToolHelper *helper); + void Activate(); + void AfterDrawImagesEvent(); + void MouseMoveEvent(double x, double y); + void MouseButtonEvent(unsigned short int button, bool pressed); +private: + bool moving_left, moving_right, moving_top, moving_bottom, mouse_down; + double top, bottom, left, right; + double start_drag_x, start_drag_y; + HuginBase::PanoramaOptions start_drag_options, opts; +}; + +#endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-23 02:54:29 UTC (rev 3216) @@ -24,7 +24,7 @@ #include "PreviewToolHelper.h" #include "PreviewTool.h" -PreviewToolHelper::PreviewToolHelper(HuginBase::Panorama *pano_in, +PreviewToolHelper::PreviewToolHelper(PT::Panorama *pano_in, ViewState *view_state_in) { pano = pano_in; @@ -58,12 +58,12 @@ RemoveTool(tool, &image_draw_end_tools); } -void PreviewToolHelper::MouseMoved(unsigned int x, unsigned int y) +void PreviewToolHelper::MouseMoved(int x, int y) { // work out where the pointer is in the panorama. vigra::Rect2D visible = view_state->GetVisibleArea(); - mouse_x = (double) x * view_state->GetScale() + (double) visible.left(); - mouse_y = (double) y * view_state->GetScale() + (double) visible.top(); + mouse_x = (double) x / view_state->GetScale() + (double) visible.left(); + mouse_y = (double) y / view_state->GetScale() + (double) visible.top(); // now tell tools that want notification. std::set<PreviewTool *>::iterator iterator; for (iterator = mouse_move_notified_tools.begin(); @@ -158,7 +158,7 @@ return view_state; } -HuginBase::Panorama *PreviewToolHelper::GetPanoramaPtr() +PT::Panorama *PreviewToolHelper::GetPanoramaPtr() { return pano; } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-23 02:54:29 UTC (rev 3216) @@ -56,7 +56,7 @@ #include <utility> #include "ViewState.h" -#include <panodata/Panorama.h> +#include "panoinc.h" class PreviewTool; @@ -68,7 +68,7 @@ MOUSE_MOVE, MOUSE_PRESS, KEY_PRESS, DRAW_UNDER_IMAGES, DRAW_OVER_IMAGES, }; - PreviewToolHelper(HuginBase::Panorama *pano, + PreviewToolHelper(PT::Panorama *pano, ViewState *view_state); ~PreviewToolHelper(); // working with tools @@ -79,7 +79,7 @@ void DeactivateTool(PreviewTool *tool); // Events - void MouseMoved(unsigned int x, unsigned int y); + void MouseMoved(int x, int y); // pressed is true if the button is pushed down, false if let go void MouseButtonEvent(unsigned short int button, bool pressed); // keycode is the wxWidgets keycode. @@ -95,7 +95,7 @@ std::set<unsigned int> GetImageNumbersUnderMouse(); std::pair<double, double> GetMousePosition(); ViewState *GetViewStatePtr(); - HuginBase::Panorama *GetPanoramaPtr(); + PT::Panorama *GetPanoramaPtr(); // Setting up notifications void NotifyMe(Event event, PreviewTool *tool); @@ -106,7 +106,7 @@ void DoNotNotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); private: std::set<PreviewTool *> tools_deactivated; - HuginBase::Panorama *pano; + PT::Panorama *pano; ViewState *view_state; double mouse_x, mouse_y; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp 2008-07-23 02:54:29 UTC (rev 3216) @@ -219,6 +219,22 @@ img_states[image_nr] = *new_img; } +void ViewState::ForceRequireRedraw() +{ + // this is generally called by preview tools. We let them manage themselves. + // often they give some user interface thing that doesn't reflect a change + // in the panorama at all, so we let them force a redraw. + dirty_draw = true; +} + +void ViewState::Redraw() +{ + if (RequireDraw()) + { + RefreshFunc(refreshArg); + } +} + HuginBase::PanoramaOptions *ViewState::GetOptions() { return &opts; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-07-22 05:00:01 UTC (rev 3215) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-07-23 02:54:29 UTC (rev 3216) @@ -74,6 +74,8 @@ void SetOptions(const HuginBase::PanoramaOptions *new_opts); void SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage *new_img); void SetLens(unsigned int lens_nr, HuginBase::Lens *new_lens); + // someone else decides we need to redraw next time around. + void ForceRequireRedraw(); // then we compare with the stored state and set dirty flags as neceassry. HuginBase::PanoramaOptions *GetOptions(); @@ -114,6 +116,9 @@ { return visible_area; } + + // redraw the preview + void Redraw(); protected: HuginBase::Panorama *m_pano; float scale, genscale; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-23 16:07:05
|
Revision: 3217 http://hugin.svn.sourceforge.net/hugin/?rev=3217&view=rev Author: jlegg Date: 2008-07-23 16:06:59 +0000 (Wed, 23 Jul 2008) Log Message: ----------- Removed some of the functionality of the TextureManager, so it works with Ubuntu Hardy's buggy ati driver (will make it much slower in certain situations, but doesn't crash). Some usability improvements for the crop tool. Changed the way the offset between the corner of the OpenGL viewport and the corner of the panorama was reported. (Thanks Pablo) Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-23 02:54:29 UTC (rev 3216) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-23 16:06:59 UTC (rev 3217) @@ -968,10 +968,9 @@ { helper->ActivateTool(crop_tool); } else { + // the tool draws some extra guides that need covering up + m_GLViewer->Refresh(); helper->DeactivateTool(crop_tool); } - // the tool draws some extra guides that need to be shown when starting or - // covered up when done; therefore update the display. - m_GLViewer->Refresh(); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-23 02:54:29 UTC (rev 3216) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-23 16:06:59 UTC (rev 3217) @@ -64,7 +64,7 @@ { } -std::pair<int, int> GLRenderer::Resize(int in_width, int in_height) +vigra::Diff2D GLRenderer::Resize(int in_width, int in_height) { width = in_width; height = in_height; @@ -101,7 +101,9 @@ m_view_state->SetVisibleArea(vigra::Rect2D(0, 0, options->getWidth(), options->getHeight())); m_view_state->SetScale(1.0 / scale); - return std::pair<int, int>(int (x_offs / scale), int (y_offs / scale)); + // return the offset from the top left corner of the viewpoer to the top left + // corner of the panorama. + return vigra::Diff2D(int (x_offs / scale), int (y_offs / scale)); } void GLRenderer::SetBackground(unsigned char red, unsigned char green, unsigned char blue) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-07-23 02:54:29 UTC (rev 3216) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-07-23 16:06:59 UTC (rev 3217) @@ -36,6 +36,7 @@ #define DEBUG_HEADER "" #include <base_wx/ImageCache.h> #include <vigra_ext/ROIImage.h> +#include <vigra/diff2d.hxx> #include <utility> class PreviewToolHelper; @@ -55,7 +56,7 @@ // resize the viewport, because the window's dimensions have changed. // returns the number of screen pixels until the start of the panorma, // both horizontally and vertically. - std::pair<int, int> Resize(int width, int height); + vigra::Diff2D Resize(int width, int height); // void panoramaChanged(PT::Panorama &pano); // void panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet & imgNr); void Redraw(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-07-23 02:54:29 UTC (rev 3216) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-07-23 16:06:59 UTC (rev 3217) @@ -180,8 +180,8 @@ void GLViewer::MouseMotion(wxMouseEvent& e) { - m_tool_helper->MouseMoved((int) e.m_x - offset.first, - (int) e.m_y - offset.second); + m_tool_helper->MouseMoved((int) e.m_x - offset.x, + (int) e.m_y - offset.y); } void GLViewer::LeftDown(wxMouseEvent& e) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-07-23 02:54:29 UTC (rev 3216) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-07-23 16:06:59 UTC (rev 3217) @@ -27,6 +27,7 @@ #include "ViewState.h" #include <wx/glcanvas.h> #include <utility> +#include <vigra/diff2d.hxx> class GLRenderer; class TextureManager; @@ -62,7 +63,7 @@ wxGLContext *m_glContext; PT::Panorama * m_pano; bool started_creation; - std::pair<int, int> offset; + vigra::Diff2D offset; GLPreviewFrame *frame; }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-07-23 02:54:29 UTC (rev 3216) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-07-23 16:06:59 UTC (rev 3217) @@ -62,24 +62,15 @@ vigra::Rect2D roi = opts->getROI(); double width = (double) roi.width(), height = (double) roi.height(), - margin = (width > height ? height : width) / 4.0, - o_width = opts->getSize().width(), - o_height = opts->getSize().height(); + margin = (width > height ? height : width) / 4.0; top = (double) roi.top() + margin; bottom = (double) roi.bottom() - margin; left = (double) roi.left() + margin; right = (double) roi.right() - margin; - // actually draw the lines, invert colours under them. - glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); - glBegin(GL_LINES); - glVertex2d(0.0, top); glVertex2d(o_width, top); - glVertex2d(0.0, bottom); glVertex2d(o_width, bottom); - glVertex2d(left, 0.0); glVertex2d(left, o_height); - glVertex2d(right, 0.0); glVertex2d(right, o_height); - glEnd(); + // now draw boxes to indicate what dragging would do. if (!mouse_down) { @@ -150,28 +141,44 @@ // Note that since we normally only allow redraws to rerender the scene // if the view of the panorama has changed, we have to force a redraw. // (our moving boxes aren't known by the view_state!) + int changes = 0; if ((x < left) != moving_left) { moving_left = !moving_left; - helper->GetViewStatePtr()->ForceRequireRedraw(); + changes++; } if ((x > right) != moving_right) { moving_right = !moving_right; - helper->GetViewStatePtr()->ForceRequireRedraw(); + changes++; } if ((y < top) != moving_top) { moving_top = !moving_top; - helper->GetViewStatePtr()->ForceRequireRedraw(); + changes++; } if ((y > bottom) != moving_bottom) { moving_bottom = !moving_bottom; + changes++; + } + if (!(moving_left || moving_right || moving_top || moving_bottom)) + { + // in the middle moves the whole region + moving_left = true; moving_right = true; + moving_top = true; moving_bottom = true; + changes++; + } + // the middle section is an exception to the other 4 rules: + if (changes == 5) changes = 0; + // Draw if the boxes we show are different to what is already drawn. + if (changes) + { + // since we didn't change the panorama, view_state doesn't think we + // should redraw. Persuade it otherwise: helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); // now redraw. } - // This will only redraw again if any of the above conditionals ran. - helper->GetViewStatePtr()->Redraw(); } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-07-23 02:54:29 UTC (rev 3216) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-07-23 16:06:59 UTC (rev 3217) @@ -30,19 +30,8 @@ // minor diffferences, uses wxwidgets for platform detection: #include <wx/wx.h> #include <wx/platform.h> -// TODO IIRC this is how you include openGL on OS X. Is it the same with cmake? -#ifdef __WXMAC__ -#include <OpenGL/gl.h> -#include <OpenGL/glu.h> -#else -// Windows' GL/gl.h needs windows.h to be included first -#ifdef __WXMSW__ -# include <vigra/windows.h> -#endif -// other platforms #include <GL/gl.h> #include <GL/glu.h> -#endif #include <config.h> #include "panoinc_WX.h" @@ -201,6 +190,11 @@ TextureKey key(img_p, &photometric_correct); it = textures.find(key); TextureInfo *texinfo; + /* This section would allow us to reuse textures generated when we want + * to change the size. It is not used as it causes segmentation faults + * under Ubuntu 8.04's "ati" graphics driver. + */ + #if 0 if (it == textures.end()) { // We haven't seen this image before. @@ -295,8 +289,72 @@ texinfo->min_lod = mip_level; } } + #endif + /* Instead of the above section, replace the whole texture when appropriate: + */ + // Find a size for it + double hfov = img_p->getHFOV(), + aspect = double (img_p->getSize().height()) + / double (img_p->getSize().width()), + ideal_texels = texel_density * hfov * aspect, + // we would like a texture this size: + ideal_tex_width = sqrt(ideal_texels / aspect), + ideal_tex_height = aspect * ideal_tex_width; + // we will need to round up/down to a power of two + // store the power that 2 is raised to, not the actual size + unsigned int tex_width_p = int(log2(ideal_tex_width)), + tex_height_p = int(log2(ideal_tex_height)); + // check this is hardware supported. + { + unsigned int biggest = GetMaxTextureSizePower(); + if (biggest < tex_width_p) tex_width_p = biggest; + if (biggest < tex_height_p) tex_height_p = biggest; + } + + // check if this is over budget. + ideal_texels_used += ideal_texels; + // while the texture is over budget, shrink it + while ( (texels_used + 1 << (tex_width_p + tex_height_p)) + > ideal_texels_used) + { + // smaller aspect means the texture is wider. + if ((double) (1 << tex_height_p) / (double) (1 << tex_width_p) + < aspect) + { + tex_width_p--; + } else { + tex_height_p--; + } + } + // we have a nice size + texels_used += 1 << (tex_width_p + tex_height_p); + if ( it == textures.end() + || (it->second).width_p != tex_width_p + || (it->second).height_p != tex_height_p) + { + // Either: 1. We haven't seen this image before + // or: 2. Our texture for this is image is the wrong size + // ...therefore we make a new one the right size: + std::pair<std::map<TextureKey, TextureInfo>::iterator, bool> ins; + ins = textures.insert(std::pair<TextureKey, TextureInfo> + (TextureKey(img_p, &photometric_correct), + // the key is used to identify the image with (or without) + // photometric correction parameters. + TextureInfo(tex_width_p, tex_height_p) + )); + // create and upload the texture image + texinfo = &((ins.first)->second); + texinfo->DefineLevels(0, // minimum mip level + // maximum mip level + tex_width_p > tex_height_p ? tex_width_p : tex_height_p, + photometric_correct, + dest_img, + view_state->GetSrcImage(image_index)); + } + } // We should remove any images' texture when it is no longer in the panorama - if (photometric_correct || view_state->ImagesRemoved()) + // with the ati bug work around, we might make unneassry textures whenever + //if (photometric_correct || view_state->ImagesRemoved()) { CleanTextures(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-26 03:14:01
|
Revision: 3240 http://hugin.svn.sourceforge.net/hugin/?rev=3240&view=rev Author: jlegg Date: 2008-07-26 03:13:58 +0000 (Sat, 26 Jul 2008) Log Message: ----------- Started Drag tool, fixed clipping corruption bug, and fixed aspect ratio of circular crop wrong bug. There is still some improvements needed in circular cropping. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-07-26 03:13:58 UTC (rev 3240) @@ -32,7 +32,7 @@ HFOVDialog.cpp TextureManager.cpp MeshRemapper.cpp VertexCoordRemapper.cpp TexCoordRemapper.cpp ChoosyRemapper.cpp MeshManager.cpp ViewState.cpp OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp -PreviewCropTool.cpp) +PreviewCropTool.cpp PreviewDragTool.cpp) IF(APPLE) if (MAC_SELF_CONTAINED_BUNDLE) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-26 03:13:58 UTC (rev 3240) @@ -963,14 +963,14 @@ void GLPreviewFrame::OnCrop(wxCommandEvent & e) { - // turn on or off the crop tool when it's button is pressed. + // turn on or off the crop tool when its button is pressed. if (e.IsChecked()) { helper->ActivateTool(crop_tool); } else { + helper->DeactivateTool(crop_tool); // the tool draws some extra guides that need covering up m_GLViewer->Refresh(); - helper->DeactivateTool(crop_tool); } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-26 03:13:58 UTC (rev 3240) @@ -71,12 +71,13 @@ circle_crop = src->getCropMode() == HuginBase::SrcPanoImage::CROP_CIRCLE; if (circle_crop) { + circle_crop_aspect = height / width; + //circle_crop_aspect *= circle_crop_aspect; circle_crop_centre_x = (crop_x1 + crop_x2) / 2.0; circle_crop_centre_y = (crop_y1 + crop_y2) / 2.0; double width = crop_x2 - crop_x1, height = crop_y2 - crop_y1; - circle_crop_radius = width < height ? width : height; - circle_crop_radius /= 2.0; + circle_crop_radius = (width < height ? width : height) / 2.0; } // hugin allows negative cropping regions, but we are expected to only // output the regions that exist in the original image, so clamp the values: @@ -191,8 +192,8 @@ // now substitute t into the edge we are testing's line: x = dx * t + v1->tex_c[0], y = dy * t + v1->tex_c[1], - // move the vertex coordinates to match the texture ones. - // t = 0 would give v1, t = 1 would give v2; so we linearly interpolate by t: + // move the vertex coordinates to match the texture ones. + // t = 0 would give v1, t = 1 would give v2; so we linearly interpolate by t: td1 = 1.0 - t, xc = v1->vertex_c[0] * td1 + v2->vertex_c[0] * t, yc = v1->vertex_c[1] * td1 + v2->vertex_c[1] * t; @@ -327,14 +328,21 @@ * image is contained within the input face, but then the interpolation * there would make it well out of sync anyway, so it's no big deal. */ + /* Since the coordinates are scaled to between 0 and 1, we actually need to + * crop to a elipse to get the aspect ratio right. + */ if (circle_crop) { - for (unsigned int edge = 0; edge < circle_clip_detail; edge++) + for (unsigned int edge = 0; edge < /*4*/ circle_clip_detail; edge++) { + /*double angle =-M_PI / 2.0 - atan2(face->tex_c[edge % 2][edge / 2][0] + - circle_crop_centre_x, + face->tex_c[edge % 2][edge / 2][1] + - circle_crop_centre_y),*/ double angle = (double) edge * circle_clip_inc, - ac_x = sin(angle), - ac_y = cos(angle), - clip_line[3] = {ac_x, ac_y, circle_crop_radius + ac_x = sin(angle) / (circle_crop_radius * circle_crop_aspect), + ac_y = cos(angle) / circle_crop_radius, + clip_line[3] = {ac_x, ac_y, 1.0 - ac_x * circle_crop_centre_x - ac_y * circle_crop_centre_y}; poly = poly.Clip(clip_line); @@ -358,8 +366,8 @@ { for (unsigned short int c = 0; c < 2; c++) { - result->tex_c[x][y][0] = face_list.back().tex_c[x][y][0]; - result->vertex_c[x][y][0] = face_list.back().vertex_c[x][y][0]; + result->tex_c[x][y][c] = face_list.back().tex_c[x][y][c]; + result->vertex_c[x][y][c] = face_list.back().vertex_c[x][y][c]; } } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-26 03:13:58 UTC (rev 3240) @@ -91,7 +91,8 @@ // cropping of the source image HuginBase::SrcPanoImage::CropMode crop_mode; double crop_x1, crop_x2, crop_y1, crop_y2, - circle_crop_centre_x, circle_crop_centre_y, circle_crop_radius; + circle_crop_centre_x, circle_crop_centre_y, circle_crop_radius, + circle_crop_aspect; bool circle_crop; void SetCrop(); // fill the above values // crop a face to the source image, return true if there is anything left. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-07-26 03:13:58 UTC (rev 3240) @@ -122,3 +122,22 @@ return result * -2.0 + proj->getSize()->x; } + +// Use the transformations to get arbitary points. + +bool OutputProjectionInfo::AngularToImage(double &image_x, double &image_y, + double yaw, double pitch) +{ + return transform.transformImgCoord(image_x, image_y, + yaw + 180.0, pitch + 90.0); +} + +bool OutputProjectionInfo::ImageToAngular(double &yaw, double &pitch, + double image_x, double image_y) +{ + bool r = reverse_transform.transformImgCoord(yaw, pitch, image_x, image_y); + yaw -= 180.0; + pitch -= 90.0; + return r; +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.h 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.h 2008-07-26 03:13:58 UTC (rev 3240) @@ -73,6 +73,9 @@ {return south_pole_x;} const double GetSouthPoleY() const {return south_pole_y;} + // use the transformation for anything else + bool AngularToImage(double &image_x, double &image_y, double yaw, double pitch); + bool ImageToAngular(double &yaw, double &pitch, double image_x, double image_y); private: double lower_x, middle_x, upper_x, lower_y, middle_y, upper_y, Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-07-26 03:13:58 UTC (rev 3240) @@ -0,0 +1,124 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewDragTool.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "PreviewDragTool.h" +#include <math.h> + +PreviewDragTool::PreviewDragTool(PreviewToolHelper *helper) + : PreviewTool(helper) +{ +} + +void PreviewDragTool::Activate() +{ + drag_yaw = false; drag_pitch = false; drag_roll = false; + shift = false; control = false; alt = false; + // register notifications + helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); + helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); + helper->NotifyMe(PreviewToolHelper::KEY_PRESS, this); +} + +void PreviewDragTool::MouseMoveEvent(double x, double y) +{ + if (drag_yaw || drag_pitch || drag_roll) + { + // move the selected images on the tempory copies. + // redraw + } +} + +void PreviewDragTool::MouseButtonEvent(unsigned short int button, bool pressed) +{ + if (pressed) + { + switch (button) + { + // primary button + case 0: + // different things depending on modifier keys. + if (!(alt && shift && control)) + { + // no keys + drag_yaw = true; drag_pitch = true; + } + else if (shift && !(control || alt)) + { + drag_pitch = true; + } + else if (control && !(alt || shift)) + { + drag_roll = true; + } + else if (alt && !(control || shift)) + { + drag_yaw = true; + } + break; + case 1: + if (!(alt && shift && control)) + { + drag_roll = true; + } + break; + } + if (drag_roll) + { + // set centre and angle + HuginBase::PanoramaOptions *opts + = helper->GetViewStatePtr()->GetOptions(); + centre.x = double (opts->getSize().width()) / 2.0; + centre.y = double (opts->getSize().height()) / 2.0; + hugin_utils::FDiff2D angular = centre - helper->GetMousePosition(); + start_angle = atan2(angular.y, angular.x); + } + if (drag_yaw || drag_pitch) + { + // set angles + hugin_utils::FDiff2D mouse_pos = helper->GetMousePosition(); + double yaw, pitch; + helper->GetViewStatePtr()->GetProjectionInfo()->ImageToAngular(yaw, + pitch, mouse_pos.x, mouse_pos.y); + start_coordinates.x = yaw; + start_coordinates.y = pitch; + } + if (drag_roll || drag_yaw || drag_pitch) + { + // record where the images are so we know what the difference is. + // TODO use the topmost drawn component instead of all of the images + // directly under the cursor. + dragging_images = helper->GetImageNumbersUnderMouse(); + // TODO record where they are. + } + } else { + // apply rotations permanently + // stop dragging + drag_yaw = false; drag_pitch = false; drag_roll = false; + } +} + +void PreviewDragTool::KeypressEvent(int keycode, bool pressed) +{ + if (keycode == WXK_SHIFT) shift = pressed; + if (keycode == WXK_CONTROL) control = pressed; + if (keycode == WXK_ALT) alt = pressed; +} + Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-07-26 03:13:58 UTC (rev 3240) @@ -0,0 +1,67 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewDragTool.h + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This tool allows the user to change the yaw, pitch and roll of a connected + * component of images by dragging them. + * If there are multiple components under the pointer when the user begins to + * drag, the lowest number one is chosen, since it is drawn on top. + * + * Modifiers | Variables changed + * none | yaw and pitch + * shift | pitch + * control | roll + * alt | yaw + * + * You can also change only pitch by using the secondary mouse button (if there + * is one). + * + *(Reasoning: control click on mac is equivalent right click on other platforms, + * no modifiers should be close to old behaviour, where modifiers were not used, + * shift and alt chosen arbitrarily but more portable than meta or the like.) + */ + +#ifndef _PREVIEWDRAGTOOL_H +#define _PREVIEWDRAGTOOL_H + +#include "PreviewTool.h" + +#include <set> + +class PreviewDragTool : public PreviewTool +{ +public: + PreviewDragTool(PreviewToolHelper *helper); + void Activate(); + void MouseMoveEvent(double x, double y); + void MouseButtonEvent(unsigned short int button, bool pressed); + void KeypressEvent(int keycode, bool pressed); +private: + std::set<unsigned int> dragging_images; + bool drag_yaw; + bool drag_pitch; + bool drag_roll; + double start_angle; + hugin_utils::FDiff2D centre; + hugin_utils::FDiff2D start_coordinates; + bool shift, control, alt; +}; + +#endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-26 03:13:58 UTC (rev 3240) @@ -148,9 +148,9 @@ return images_under_mouse; } -std::pair<double, double> PreviewToolHelper::GetMousePosition() +hugin_utils::FDiff2D PreviewToolHelper::GetMousePosition() { - return std::pair<unsigned int, unsigned int>(mouse_x, mouse_y); + return hugin_utils::FDiff2D(mouse_x, mouse_y); } ViewState *PreviewToolHelper::GetViewStatePtr() Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-26 03:13:58 UTC (rev 3240) @@ -55,6 +55,7 @@ #include <vector> #include <utility> +#include <hugin_math/hugin_math.h> #include "ViewState.h" #include "panoinc.h" @@ -93,7 +94,7 @@ // Get information std::set<unsigned int> GetImageNumbersUnderMouse(); - std::pair<double, double> GetMousePosition(); + hugin_utils::FDiff2D GetMousePosition(); ViewState *GetViewStatePtr(); PT::Panorama *GetPanoramaPtr(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-07-25 17:04:06 UTC (rev 3239) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-07-26 03:13:58 UTC (rev 3240) @@ -113,7 +113,7 @@ /* Since we only crop to convex regions, having all four points inside the * wanted region implies we don't need to do any clipping. It should be * faster to test for this and skip full clipping in that case, as the vast - * majority of faces will not need any clipping. + * majority of faces will not need any clipping or fail the test above. */ HuginBase::SrcPanoImage *src_img = view_state->GetSrcImage(image_number); if ( src_img->isInside(vigra::Point2D(int(result->tex_c[0][0][0] * width), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-07-27 18:55:58
|
Revision: 3241 http://hugin.svn.sourceforge.net/hugin/?rev=3241&view=rev Author: jlegg Date: 2008-07-27 18:55:54 +0000 (Sun, 27 Jul 2008) Log Message: ----------- Drag tool implemented, the user can rotate the panorama interactively. Modifier keys restrict the direction. Efficiency of circular cropping improved. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -56,7 +56,9 @@ } #include "PreviewToolHelper.h" +#include "PreviewTool.h" #include "PreviewCropTool.h" +#include "PreviewDragTool.h" using namespace utils; @@ -85,6 +87,7 @@ EVT_TOOL(XRCID("preview_show_none_tool"), GLPreviewFrame::OnShowNone) EVT_TOOL(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric) EVT_TOOL(XRCID("preview_crop_tool"), GLPreviewFrame::OnCrop) + EVT_TOOL(XRCID("preview_drag_tool"), GLPreviewFrame::OnDrag) EVT_TEXT_ENTER( -1 , GLPreviewFrame::OnTextCtrlChanged) @@ -959,6 +962,7 @@ // create texture objects and display lists before they are used. helper = helper_in; crop_tool = new PreviewCropTool(helper); + drag_tool = new PreviewDragTool(helper); } void GLPreviewFrame::OnCrop(wxCommandEvent & e) @@ -967,6 +971,7 @@ if (e.IsChecked()) { helper->ActivateTool(crop_tool); + // TODO deactivate the buttons for tools this turns off. } else { helper->DeactivateTool(crop_tool); // the tool draws some extra guides that need covering up @@ -974,3 +979,14 @@ } } +void GLPreviewFrame::OnDrag(wxCommandEvent & e) +{ + if (e.IsChecked()) + { + helper->ActivateTool(drag_tool); + // TODO deactivate the buttons for tools this turns off. + } else { + helper->DeactivateTool(drag_tool); + } + m_GLViewer->Refresh(); +} Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -27,8 +27,10 @@ class wxToggleButton; class wxCheckBox; class GLViewer; + class PreviewToolHelper; class PreviewCropTool; +class PreviewDragTool; /** The OpenGL preview frame * @@ -66,6 +68,7 @@ void OnShowNone(wxCommandEvent & e); void OnPhotometric(wxCommandEvent & e); void OnCrop(wxCommandEvent & e); + void OnDrag(wxCommandEvent & e); void OnNumTransform(wxCommandEvent & e); void OnChangeFOV(wxScrollEvent & e); void OnTrackChangeFOV(wxScrollEvent & e); @@ -120,6 +123,7 @@ // tools PreviewToolHelper *helper; PreviewCropTool *crop_tool; + PreviewDragTool *drag_tool; }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -162,18 +162,10 @@ glVertex2f(0.0, height_o); glVertex2i(roi.left(), roi.bottom()); glVertex2f(0.0, 0.0); glVertex2i(roi.left(), roi.top()); glEnd(); - // draw lines down the middle and around the cropped area. + // draw lines around cropped area. // we want to invert the color to make it stand out. glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); glColor3f(1.0, 1.0, 1.0); - // centre lines - glBegin(GL_LINES); - glVertex2f(width_o / 2.0, 0.0); - glVertex2f(width_o / 2.0, height_o); - glVertex2f(0.0, height_o / 2.0); - glVertex2f(width_o, height_o / 2.0); - glEnd(); - // border of cropped area. glBegin(GL_LINE_LOOP); glVertex2i(roi.left(), roi.top()); glVertex2i(roi.right(), roi.top()); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -45,6 +45,9 @@ EVT_LEFT_UP (GLViewer::LeftUp) EVT_RIGHT_DOWN (GLViewer::RightDown) EVT_RIGHT_UP (GLViewer::RightUp) + // keyboard events + EVT_KEY_DOWN(GLViewer::KeyDown) + EVT_KEY_UP(GLViewer::KeyUp) END_EVENT_TABLE() GLViewer::GLViewer(wxFrame* parent, PT::Panorama &pano, int args[], GLPreviewFrame *frame_in) : @@ -186,21 +189,31 @@ void GLViewer::LeftDown(wxMouseEvent& e) { - m_tool_helper->MouseButtonEvent(0, true); + m_tool_helper->MouseButtonEvent(e); } void GLViewer::LeftUp(wxMouseEvent& e) { - m_tool_helper->MouseButtonEvent(0, false); + m_tool_helper->MouseButtonEvent(e); } void GLViewer::RightDown(wxMouseEvent& e) { - m_tool_helper->MouseButtonEvent(1, true); + m_tool_helper->MouseButtonEvent(e); } void GLViewer::RightUp(wxMouseEvent& e) { - m_tool_helper->MouseButtonEvent(1, false); + m_tool_helper->MouseButtonEvent(e); } +void GLViewer::KeyDown(wxKeyEvent& e) +{ + m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true); +} + +void GLViewer::KeyUp(wxKeyEvent& e) +{ + m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false); +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -47,21 +47,25 @@ void SetUpContext(); void SetPhotometricCorrect(bool state); + ViewState * m_view_state; +protected: void MouseMotion(wxMouseEvent& e); void LeftDown(wxMouseEvent& e); void LeftUp(wxMouseEvent& e); void RightDown(wxMouseEvent& e); void RightUp(wxMouseEvent& e); + void KeyDown(wxKeyEvent & e); + void KeyUp(wxKeyEvent & e); - ViewState * m_view_state; -protected: DECLARE_EVENT_TABLE() + PreviewToolHelper *m_tool_helper; GLRenderer *m_renderer; TextureManager *m_tex_manager; MeshManager *m_mesh_manager; wxGLContext *m_glContext; PT::Panorama * m_pano; + bool started_creation; vigra::Diff2D offset; GLPreviewFrame *frame; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -24,12 +24,6 @@ #include "MeshRemapper.h" #include "ViewState.h" -// The number of sides to give the regular sided polygon we use for circular -// clipping, higher is more accurate but slower. -const unsigned int circle_clip_detail = 32; -// the angle across each edge given the abpve. -const double circle_clip_inc = (double) circle_clip_detail / (2.0 * M_PI); - MeshRemapper::MeshRemapper(HuginBase::Panorama *m_pano_in, unsigned int image_number_in, ViewState *view_state_in) @@ -71,13 +65,14 @@ circle_crop = src->getCropMode() == HuginBase::SrcPanoImage::CROP_CIRCLE; if (circle_crop) { - circle_crop_aspect = height / width; - //circle_crop_aspect *= circle_crop_aspect; circle_crop_centre_x = (crop_x1 + crop_x2) / 2.0; circle_crop_centre_y = (crop_y1 + crop_y2) / 2.0; - double width = crop_x2 - crop_x1, - height = crop_y2 - crop_y1; - circle_crop_radius = (width < height ? width : height) / 2.0; + double crop_width_px = (double) src->getCropRect().width(), + crop_hieght_px = (double) src->getCropRect().height(), + crop_radius = (crop_width_px < crop_hieght_px ? + crop_width_px : crop_hieght_px) / 2.0; + circle_crop_radius_x = crop_radius / width; + circle_crop_radius_y = crop_radius / height; } // hugin allows negative cropping regions, but we are expected to only // output the regions that exist in the original image, so clamp the values: @@ -319,32 +314,28 @@ poly = poly.Clip(clip_lines[1]); poly = poly.Clip(clip_lines[2]); poly = poly.Clip(clip_lines[3]); - // Feign circular clipping by trimming to a many-sided regular polygon. - /* TODO We should get better circle cropping if we work out what angle to - * clip at based on the locations of the vertices. Then we could clip for - * the angles in the circle at each vertex and have far less clips, more - * detail, and reduce the number of vertices where the corners are as well. - * This will only break down where {a huge part / all / even more} of the - * image is contained within the input face, but then the interpolation - * there would make it well out of sync anyway, so it's no big deal. + // Feign circular clipping by trimming to some tangent lines. + /* Work out what angles to clip to based on the locations of the vertices. + * This is generally good, although it will break down where {a huge part / + * all / even more} of the image contained within the input face. However in + * this case the interpolation would make it well out of sync anyway, so + * it's no big deal. */ /* Since the coordinates are scaled to between 0 and 1, we actually need to * crop to a elipse to get the aspect ratio right. */ if (circle_crop) { - for (unsigned int edge = 0; edge < /*4*/ circle_clip_detail; edge++) + for (unsigned int edge = 0; edge < 4; edge++) { - /*double angle =-M_PI / 2.0 - atan2(face->tex_c[edge % 2][edge / 2][0] - - circle_crop_centre_x, - face->tex_c[edge % 2][edge / 2][1] - - circle_crop_centre_y),*/ - double angle = (double) edge * circle_clip_inc, - ac_x = sin(angle) / (circle_crop_radius * circle_crop_aspect), - ac_y = cos(angle) / circle_crop_radius, - clip_line[3] = {ac_x, ac_y, 1.0 - - ac_x * circle_crop_centre_x - - ac_y * circle_crop_centre_y}; + double angle = M_PI + atan2(face->tex_c[edge % 2][edge / 2][1] + - circle_crop_centre_y, + face->tex_c[edge % 2][edge / 2][0] + - circle_crop_centre_x), + ac_x = cos(angle) / circle_crop_radius_x, + ac_y = sin(angle) / circle_crop_radius_y, + clip_line[3] = {ac_x, ac_y, 1.0 - ac_x * circle_crop_centre_x + - ac_y * circle_crop_centre_y}; poly = poly.Clip(clip_line); } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -91,8 +91,8 @@ // cropping of the source image HuginBase::SrcPanoImage::CropMode crop_mode; double crop_x1, crop_x2, crop_y1, crop_y2, - circle_crop_centre_x, circle_crop_centre_y, circle_crop_radius, - circle_crop_aspect; + circle_crop_centre_x, circle_crop_centre_y, + circle_crop_radius_x, circle_crop_radius_y; bool circle_crop; void SetCrop(); // fill the above values // crop a face to the source image, return true if there is anything left. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -183,11 +183,11 @@ } -void PreviewCropTool::MouseButtonEvent(unsigned short int button, bool pressed) +void PreviewCropTool::MouseButtonEvent(wxMouseEvent &e) { - if (button == 0) + if (e.GetButton() == wxMOUSE_BTN_LEFT) { - if (pressed) + if (e.ButtonDown()) { start_drag_options = *helper->GetViewStatePtr()->GetOptions(); opts = start_drag_options; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -35,7 +35,7 @@ void Activate(); void AfterDrawImagesEvent(); void MouseMoveEvent(double x, double y); - void MouseButtonEvent(unsigned short int button, bool pressed); + void MouseButtonEvent(wxMouseEvent &e); private: bool moving_left, moving_right, moving_top, moving_bottom, mouse_down; double top, bottom, left, right; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -20,7 +20,9 @@ */ #include "PreviewDragTool.h" +#include "CommandHistory.h" #include <math.h> +#include <GL/gl.h> PreviewDragTool::PreviewDragTool(PreviewToolHelper *helper) : PreviewTool(helper) @@ -35,27 +37,60 @@ helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); helper->NotifyMe(PreviewToolHelper::KEY_PRESS, this); + helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); } void PreviewDragTool::MouseMoveEvent(double x, double y) { if (drag_yaw || drag_pitch || drag_roll) { - // move the selected images on the tempory copies. + // how far are we moving? + if (drag_yaw || drag_pitch) + { + double yaw, pitch; + helper->GetViewStatePtr()->GetProjectionInfo()->ImageToAngular(yaw, + pitch, x, y); + shift_coordinates.x = yaw - start_coordinates.x; + shift_coordinates.y = start_coordinates.y - pitch; + if (!drag_yaw) shift_coordinates.x = 0.0; + if (!drag_pitch) shift_coordinates.y = 0.0; + } + if (drag_roll) + { + shift_angle = RAD_TO_DEG(atan2(y - centre.y, x- centre.x) - + start_angle); + } + // move the selected images on the tempory copies for display. + std::map<unsigned int, AngleStore>::iterator i; + for (i = image_angles.begin(); i != image_angles.end(); i++ ) + { + HuginBase::SrcPanoImage img = *helper->GetViewStatePtr()-> + GetSrcImage(i->first); + double new_yaw, new_pitch, new_roll; + i->second.Move(shift_coordinates.x, shift_coordinates.y, + shift_angle, + new_yaw, new_pitch, new_roll); + img.setYaw(new_yaw); img.setPitch(new_pitch); img.setRoll(new_roll); + helper->GetViewStatePtr()->SetSrcImage(i->first, &img); + } // redraw + helper->GetViewStatePtr()->Redraw(); } } -void PreviewDragTool::MouseButtonEvent(unsigned short int button, bool pressed) +void PreviewDragTool::MouseButtonEvent(wxMouseEvent &e) { - if (pressed) + if (e.ButtonDown()) { - switch (button) + alt = e.m_altDown | e.m_metaDown; + control = e.m_controlDown; + shift = e.m_shiftDown; + switch (e.GetButton()) { // primary button - case 0: + case wxMOUSE_BTN_LEFT: // different things depending on modifier keys. - if (!(alt && shift && control)) + if (!(alt || shift || control)) { // no keys drag_yaw = true; drag_pitch = true; @@ -73,8 +108,8 @@ drag_yaw = true; } break; - case 1: - if (!(alt && shift && control)) + case wxMOUSE_BTN_RIGHT: + if (!(alt || shift || control)) { drag_roll = true; } @@ -87,8 +122,9 @@ = helper->GetViewStatePtr()->GetOptions(); centre.x = double (opts->getSize().width()) / 2.0; centre.y = double (opts->getSize().height()) / 2.0; - hugin_utils::FDiff2D angular = centre - helper->GetMousePosition(); + hugin_utils::FDiff2D angular = helper->GetMousePosition() - centre; start_angle = atan2(angular.y, angular.x); + shift_angle = 0.0; } if (drag_yaw || drag_pitch) { @@ -102,23 +138,98 @@ } if (drag_roll || drag_yaw || drag_pitch) { + shift_angle = 0.0; + shift_coordinates.x = 0.0; shift_coordinates.y = 0.0; // record where the images are so we know what the difference is. // TODO use the topmost drawn component instead of all of the images - // directly under the cursor. - dragging_images = helper->GetImageNumbersUnderMouse(); - // TODO record where they are. + /*std::set<unsigned int> dragging_images + = helper->GetImageNumbersUnderMouse(); + // Record where the images are. + for (std::set<unsigned int>::iterator i = dragging_images.begin(); + i != dragging_images.end(); i++) + { + image_angles[*i].Set(helper->GetViewStatePtr()-> + GetSrcImage(*i)); + }*/ + unsigned int imgs = helper->GetPanoramaPtr()->getNrOfImages(); + for (unsigned int i = 0; i < imgs; i++) + { + image_angles[i].Set(helper->GetViewStatePtr()->GetSrcImage(i)); + } } } else { // apply rotations permanently + /*for (std::map<unsigned int, AngleStore> i = image_angles.begin(); + i != image_angles.end(); i++ ) + panorama.updateVariable( i, Variable("y", y) ); + panorama.updateVariable( i, Variable("p", p) ); + panorama.updateVariable( i, Variable("r", r) ); + panorama.imageChanged(i);*/ + // TODO rotate the right stuff. + GlobalCmdHist::getInstance().addCommand( + new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), + shift_coordinates.x, shift_coordinates.y, + shift_angle) + ); // stop dragging + image_angles.clear(); drag_yaw = false; drag_pitch = false; drag_roll = false; } } -void PreviewDragTool::KeypressEvent(int keycode, bool pressed) +void PreviewDragTool::KeypressEvent(int keycode, int modifiers, bool pressed) { - if (keycode == WXK_SHIFT) shift = pressed; - if (keycode == WXK_CONTROL) control = pressed; - if (keycode == WXK_ALT) alt = pressed; + alt = modifiers & (wxMOD_ALT | wxMOD_META); + shift = modifiers & wxMOD_SHIFT; + control = modifiers & wxMOD_CONTROL; } +void PreviewDragTool::AfterDrawImagesEvent() +{ + // draw guide lines down the middle. + HuginBase::PanoramaOptions *opts = helper->GetViewStatePtr()->GetOptions(); + double width = (double) opts->getSize().width(), + height = (double) opts->getSize().height(); + // Invert the color underneath. + glDisable(GL_TEXTURE_2D); + glPushMatrix(); + glTranslatef(-0.5, -0.5, -0.5); + glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + glColor3f(1.0, 1.0, 1.0); + glBegin(GL_LINES); + glVertex2f(width / 2.0, 0.0); + glVertex2f(width / 2.0, height); + glVertex2f(0.0, height / 2.0); + glVertex2f(width, height / 2.0); + glEnd(); + glPopMatrix(); + glEnable(GL_TEXTURE_2D); +} + + +void PreviewDragTool::AngleStore::Set(HuginBase::SrcPanoImage *img) +{ + yaw = img->getYaw(); + pitch = img->getPitch(); + roll = img->getRoll(); +} + +void PreviewDragTool::AngleStore::Move(double yaw_shift, double pitch_shift, + double roll_shift, + double &yaw_out, double &pitch_out, + double &roll_out) +{ + // rotate the image around the centre point. + Matrix3 transform_matrix, original_matrix, output_matrix; + transform_matrix.SetRotationPT(DEG_TO_RAD(yaw_shift), + DEG_TO_RAD(pitch_shift), + DEG_TO_RAD(roll_shift)); + original_matrix.SetRotationPT(DEG_TO_RAD(yaw), + DEG_TO_RAD(pitch), + DEG_TO_RAD(roll)); + output_matrix = transform_matrix * original_matrix; + output_matrix.GetRotationPT(yaw_out, pitch_out, roll_out); + yaw_out = RAD_TO_DEG(yaw_out); + pitch_out = RAD_TO_DEG(pitch_out); + roll_out = RAD_TO_DEG(roll_out); +} Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -24,11 +24,11 @@ * If there are multiple components under the pointer when the user begins to * drag, the lowest number one is chosen, since it is drawn on top. * - * Modifiers | Variables changed - * none | yaw and pitch - * shift | pitch - * control | roll - * alt | yaw + * Modifiers | Variables changed + * none | yaw and pitch + * shift | pitch + * control | roll + * alt or meta | yaw * * You can also change only pitch by using the secondary mouse button (if there * is one). @@ -43,7 +43,7 @@ #include "PreviewTool.h" -#include <set> +#include <map> class PreviewDragTool : public PreviewTool { @@ -51,16 +51,23 @@ PreviewDragTool(PreviewToolHelper *helper); void Activate(); void MouseMoveEvent(double x, double y); - void MouseButtonEvent(unsigned short int button, bool pressed); - void KeypressEvent(int keycode, bool pressed); + void MouseButtonEvent(wxMouseEvent &e); + void KeypressEvent(int keycode, int modifiers, bool pressed); + void AfterDrawImagesEvent(); + class AngleStore + { + public: + double yaw, pitch, roll; + void Set(HuginBase::SrcPanoImage *img); + void Move(double yaw_shift, double pitch_shift, double roll_shift, + double &yaw_out, double &pitch_out, double &roll_out); + }; private: - std::set<unsigned int> dragging_images; - bool drag_yaw; - bool drag_pitch; - bool drag_roll; - double start_angle; + std::map<unsigned int, AngleStore> image_angles; + bool drag_yaw, drag_pitch, drag_roll; + double start_angle, shift_angle; hugin_utils::FDiff2D centre; - hugin_utils::FDiff2D start_coordinates; + hugin_utils::FDiff2D start_coordinates, shift_coordinates; bool shift, control, alt; }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -21,6 +21,7 @@ */ #include "PreviewTool.h" +#include "PreviewToolHelper.h" PreviewTool::PreviewTool(PreviewToolHelper *helper_in) { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -25,7 +25,11 @@ * over the preview, or changes in the panorama, and can draw extras above, * below, or instead of the panorama images. */ +#ifndef _PREVIEWTOOL_H +#define _PREVIEWTOOL_H +#include <wx/event.h> + #include "PreviewToolHelper.h" class PreviewTool @@ -43,8 +47,8 @@ // These are called when events happen, providing we requested notification. // The coordinates are in the space of the panorama output at full size. virtual void MouseMoveEvent(double x, double y) {} - virtual void MouseButtonEvent(unsigned short int button, bool pressed) {} - virtual void KeypressEvent(int keycode, bool pressed) {} + virtual void MouseButtonEvent(wxMouseEvent &e) {} + virtual void KeypressEvent(int keycode, int modifiers, bool pressed) {} // In the next few events we are free to draw stuff in OpenGL. virtual void BeforeDrawImagesEvent() {} virtual void AfterDrawImagesEvent() {} @@ -58,3 +62,5 @@ PreviewToolHelper *helper; }; +#endif + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-27 18:55:54 UTC (rev 3241) @@ -75,20 +75,20 @@ images_under_mouse_current = false; } -void PreviewToolHelper::MouseButtonEvent(unsigned short int button, bool pressed) +void PreviewToolHelper::MouseButtonEvent(wxMouseEvent &e) { // if there is a tool monitoring mouse button presses, notify it if (mouse_button_notified_tool) { - mouse_button_notified_tool->MouseButtonEvent(button, pressed); + mouse_button_notified_tool->MouseButtonEvent(e); } } -void PreviewToolHelper::KeypressEvent(int keycode, bool pressed) +void PreviewToolHelper::KeypressEvent(int keycode, int modifiers, bool pressed) { if (keypress_notified_tool) { - keypress_notified_tool->KeypressEvent(keycode, pressed); + keypress_notified_tool->KeypressEvent(keycode, modifiers, pressed); } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -51,9 +51,10 @@ #define _PREVIEWTOOLHELPER_H #include <wx/defs.h> +#include <wx/event.h> + #include <set> #include <vector> -#include <utility> #include <hugin_math/hugin_math.h> #include "ViewState.h" @@ -82,9 +83,9 @@ // Events void MouseMoved(int x, int y); // pressed is true if the button is pushed down, false if let go - void MouseButtonEvent(unsigned short int button, bool pressed); + void MouseButtonEvent(wxMouseEvent &e); // keycode is the wxWidgets keycode. - void KeypressEvent(int keycode, bool pressed); + void KeypressEvent(int keycode, int modifiers, bool pressed); void BeforeDrawImages(); void AfterDrawImages(); // Return true if we want it drawn, return false and draw the image as the Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-07-26 03:13:58 UTC (rev 3240) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-07-27 18:55:54 UTC (rev 3241) @@ -117,7 +117,7 @@ return visible_area; } - // redraw the preview + // redraw the preview, but only if something has changed. void Redraw(); protected: HuginBase::Panorama *m_pano; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-01 03:43:39
|
Revision: 3258 http://hugin.svn.sourceforge.net/hugin/?rev=3258&view=rev Author: jlegg Date: 2008-08-01 03:43:35 +0000 (Fri, 01 Aug 2008) Log Message: ----------- Mostly things for the identify tool, which isn't complete but has the basic functionality. I've also tried to get the drag tool to keep the point you start dragging under the cursor (where it is not the centre), but it jumps a bit. The TextureManager and MeshManager are now part of the ViewState object, so that tools have easy access to them. Tool's can now be notified of when the set of images under the mouse cursor change, so they don't individually check this for every mouse movement, the PreviewToolHelper does it once each time. I've fixed a bug with 180 degree boundary correction on an edge where the subdivision level was changing. I've made all images in an Alber's equal area conic projection use the TexCoordRemapper until I've worked out how to handle all the moving poles and angled seems. This isn't ideal for panoramas with many small images, and leaves a mess around the edge of the projection where I need to do some more clipping. This clipping will be different as it is in the space of the vertices and not the textures, and is specifically to get the shape of the projection. The identity tool and point to point dragging are not working completely yet, I am commiting mainly as a backup. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-08-01 03:43:35 UTC (rev 3258) @@ -32,7 +32,7 @@ HFOVDialog.cpp TextureManager.cpp MeshRemapper.cpp VertexCoordRemapper.cpp TexCoordRemapper.cpp ChoosyRemapper.cpp MeshManager.cpp ViewState.cpp OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp -PreviewCropTool.cpp PreviewDragTool.cpp) +PreviewCropTool.cpp PreviewDragTool.cpp PreviewIdentifyTool.cpp) IF(APPLE) if (MAC_SELF_CONTAINED_BUNDLE) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -60,6 +60,7 @@ case HuginBase::PanoramaOptions::STEREOGRAPHIC: case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE: case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL: + case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: // Add any projections where the poles maps to a big set of points here. // check for pole crossing { @@ -76,6 +77,17 @@ { pole = true; // it covers this pole } + if (opts->getProjection() == + HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC) + { + // always use a TexCoordRemapper for Alber's equal area conic. + pole = true; + // FIXME This is not sutible for panoramas containing many small + // images. To detect the poles in Alber's Equal area conic + // projetion, we need to account for their movement with + // changing parameters. Also the 180 degree seam goes at a + // funny angle, and we need to account for this. + } if (!pole) { // check the other pole Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -59,6 +59,7 @@ #include "PreviewTool.h" #include "PreviewCropTool.h" #include "PreviewDragTool.h" +#include "PreviewIdentifyTool.h" using namespace utils; @@ -88,6 +89,7 @@ EVT_TOOL(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric) EVT_TOOL(XRCID("preview_crop_tool"), GLPreviewFrame::OnCrop) EVT_TOOL(XRCID("preview_drag_tool"), GLPreviewFrame::OnDrag) + EVT_TOOL(XRCID("preview_identify_tool"), GLPreviewFrame::OnIdentify) EVT_TEXT_ENTER( -1 , GLPreviewFrame::OnTextCtrlChanged) @@ -102,6 +104,8 @@ #else EVT_CHECKBOX(-1, GLPreviewFrame::OnChangeDisplayedImgs) #endif + //EVT_ENTER_WINDOW(-1, GLPreviewFrame::MouseEnter) + EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV) // EVT_SCROLL_THUMBRELEASE(GLPreviewFrame::OnChangeFOV) // EVT_SCROLL_ENDSCROLL(GLPreviewFrame::OnChangeFOV) @@ -122,6 +126,13 @@ DEBUG_ASSERT(m_ToolBar); // create tool bar SetToolBar(m_ToolBar); + drag_tool_id = wxXmlResource::Get()->GetXRCID(wxT("preview_drag_tool")); + DEBUG_ASSERT(drag_tool_id != -2); + crop_tool_id = wxXmlResource::Get()->GetXRCID(wxT("preview_crop_tool")); + DEBUG_ASSERT(crop_tool_id != -2); + identify_tool_id = wxXmlResource::Get()->GetXRCID(wxT("preview_identify_tool")); + DEBUG_ASSERT(identify_tool_id != -2); + m_topsizer = new wxBoxSizer( wxVERTICAL ); @@ -963,6 +974,7 @@ helper = helper_in; crop_tool = new PreviewCropTool(helper); drag_tool = new PreviewDragTool(helper); + identify_tool = new PreviewIdentifyTool(helper, this); } void GLPreviewFrame::OnCrop(wxCommandEvent & e) @@ -970,8 +982,9 @@ // turn on or off the crop tool when its button is pressed. if (e.IsChecked()) { - helper->ActivateTool(crop_tool); - // TODO deactivate the buttons for tools this turns off. + // ActivateTool returns pointers to the tools that were switched off to + // enable the crop tool. + TurnOffTools(helper->ActivateTool(crop_tool)); } else { helper->DeactivateTool(crop_tool); // the tool draws some extra guides that need covering up @@ -983,10 +996,81 @@ { if (e.IsChecked()) { - helper->ActivateTool(drag_tool); - // TODO deactivate the buttons for tools this turns off. + TurnOffTools(helper->ActivateTool(drag_tool)); } else { helper->DeactivateTool(drag_tool); } + // The plumb lines should only be shown when the tool is active: + m_GLViewer->Refresh(); // ...draw them or draw over them. +} + +void GLPreviewFrame::OnIdentify(wxCommandEvent & e) +{ + if (e.IsChecked()) + { + TurnOffTools(helper->ActivateTool(identify_tool)); + } else { + helper->DeactivateTool(identify_tool); + CleanButtonColours(); + } m_GLViewer->Refresh(); } + +void GLPreviewFrame::TurnOffTools(std::set<PreviewTool*> tools) +{ + std::set<PreviewTool*>::iterator i; + for (i = tools.begin(); i != tools.end(); i++) + { + if (*i == crop_tool) + { + // disabled the crop tool, toogle the button for it off + m_ToolBar->ToggleTool(crop_tool_id, false); + // cover up the guidelines + m_GLViewer->Refresh(); + } else if (*i == drag_tool) + { + // disabled the drag tool, toggle its button off. + m_ToolBar->ToggleTool(drag_tool_id, false); + // cover up its boxes + m_GLViewer->Refresh(); + } else if (*i == identify_tool) + { + // disabled the identify tool, toggle its button off. + m_ToolBar->ToggleTool(identify_tool_id, false); + // cover up its indicators and restore normal button colours. + m_GLViewer->Refresh(); + CleanButtonColours(); + } + } +} + +void GLPreviewFrame::SetImageButtonColour(unsigned int image_nr, + unsigned char red, + unsigned char green, + unsigned char blue) +{ + if (red || green || blue) + { + // the identify tool wants us to highlight an image button in the given + // colour, to match up with the display in the preview. + m_ToggleButtons[image_nr]->SetBackgroundColour( + wxColour(red, green, blue)); + } else { + // return to the normal colour + m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour); + } + m_ToggleButtons[image_nr]->Refresh(); +} + +void GLPreviewFrame::CleanButtonColours() +{ + // when we turn off the identification tool, any buttons that were coloured + // to match the image in the preview should be given back the system themed + // colours. + unsigned int nr_images = m_pano.getNrOfImages(); + for (unsigned image = 0; image < nr_images; image++) + { + m_ToggleButtons[image]->SetBackgroundColour(wxNullColour); + } +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -29,8 +29,10 @@ class GLViewer; class PreviewToolHelper; +class PreviewTool; class PreviewCropTool; class PreviewDragTool; +class PreviewIdentifyTool; /** The OpenGL preview frame * @@ -57,6 +59,8 @@ void updateProgressDisplay(); void MakeTools(PreviewToolHelper * helper); + void SetImageButtonColour(unsigned int image_nr, unsigned char red, + unsigned char green, unsigned char blue); protected: void OnClose(wxCloseEvent& e); @@ -69,6 +73,7 @@ void OnPhotometric(wxCommandEvent & e); void OnCrop(wxCommandEvent & e); void OnDrag(wxCommandEvent & e); + void OnIdentify(wxCommandEvent &e); void OnNumTransform(wxCommandEvent & e); void OnChangeFOV(wxScrollEvent & e); void OnTrackChangeFOV(wxScrollEvent & e); @@ -90,6 +95,7 @@ GLViewer * m_GLViewer; wxToolBar * m_ToolBar; + int drag_tool_id, crop_tool_id, identify_tool_id; wxSlider * m_HFOVSlider; wxSlider * m_VFOVSlider; wxChoice * m_BlendModeChoice; @@ -124,6 +130,9 @@ PreviewToolHelper *helper; PreviewCropTool *crop_tool; PreviewDragTool *drag_tool; + PreviewIdentifyTool *identify_tool; + void TurnOffTools(std::set<PreviewTool*> tools); + void CleanButtonColours(); }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -55,9 +55,8 @@ 0, wxT("GLPreviewCanvas"), wxNullPalette) { m_glContext = new wxGLContext(this, 0); - + m_renderer = 0; - m_tex_manager = 0; m_pano = &pano; @@ -73,7 +72,6 @@ { delete m_tool_helper; delete m_renderer; - delete m_tex_manager; delete m_view_state; } } @@ -90,20 +88,9 @@ // that use it... so create those if necessary as well. if (!started_creation) { - started_creation = true; // It appears we are setting up for the first time. - // we need something to store the state of the view and control updates - m_view_state = new ViewState(m_pano, RefreshWrapper, this); - // Start the tools going: - m_tool_helper = new PreviewToolHelper(m_pano, m_view_state); - frame->MakeTools(m_tool_helper); - // now set the texture manager up. - m_tex_manager = new TextureManager(*m_pano, m_view_state); - // same for the mesh manager - m_mesh_manager = new MeshManager(m_pano, m_view_state); - // now make a renderer - m_renderer = new GLRenderer(m_pano, m_tex_manager, m_mesh_manager, - m_view_state, m_tool_helper); + started_creation = true; + // initialise the glew library. GLenum error_state = glewInit(); if (error_state != GLEW_OK) @@ -116,13 +103,23 @@ if (!GLEW_VERSION_1_3) { std::cerr << "Sorry, OpenGL 1.3 is required.\n"; - } + } + + // we need something to store the state of the view and control updates + m_view_state = new ViewState(m_pano, RefreshWrapper, this); + // Start the tools going: + m_tool_helper = new PreviewToolHelper(m_pano, m_view_state); + frame->MakeTools(m_tool_helper); + // now make a renderer + m_renderer = new GLRenderer(m_pano, m_view_state->GetTextureManager(), + m_view_state->GetMeshManager(), + m_view_state, m_tool_helper); } } void GLViewer::SetPhotometricCorrect(bool state) { - m_tex_manager->SetPhotometricCorrect(state); + m_view_state->GetTextureManager()->SetPhotometricCorrect(state); Refresh(); } @@ -172,8 +169,7 @@ GetClientSize(&w, &h); offset = m_renderer->Resize(w, h); } - m_tex_manager->CheckUpdate(); - m_mesh_manager->CheckUpdate(); + m_view_state->DoUpdates(); m_renderer->Redraw(); glFlush(); SwapBuffers(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -61,8 +61,6 @@ PreviewToolHelper *m_tool_helper; GLRenderer *m_renderer; - TextureManager *m_tex_manager; - MeshManager *m_mesh_manager; wxGLContext *m_glContext; PT::Panorama * m_pano; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -27,7 +27,10 @@ #ifndef _MESHMANAGER_H #define _MESHMANAGER_H +#include "PT/Panorama.h" + class MeshRemapper; +class ViewState; class MeshManager { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -162,6 +162,7 @@ const unsigned int v2_index, const double cl[3]) const { + DEBUG_ASSERT(Inside(v1_index, cl) != Inside(v2_index, cl)); // find the point of intersection from the given edge with a clip plane. // the edge is the vertex with the same number and the one before it. // Get pointers to the vertecies we will use @@ -181,6 +182,8 @@ // t * (cl[0] * dx + cl[1] * dy) + cl[0] * v1_x + cl[1] * v1_y + cl[2] = 0 // t * (cl[0] * dx + cl[1] * dy) = -cl[0] * v1_x - cl[1] * v1_y - cl[2] // so we get: + /* FIXME this assertion sometimes fails. t should always be between 0 and 1. + */ DEBUG_ASSERT(cl[0] * dx + cl[1] * dy); double t = (-cl[0] * v1->tex_c[0] - cl[1] * v1->tex_c[1] - cl[2]) / (cl[0] * dx + cl[1] * dy), @@ -192,6 +195,7 @@ td1 = 1.0 - t, xc = v1->vertex_c[0] * td1 + v2->vertex_c[0] * t, yc = v1->vertex_c[1] * td1 + v2->vertex_c[1] * t; + DEBUG_ASSERT(0.0 <= t && t <= 1.0); return Vertex(xc, yc, x, y); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -19,8 +19,14 @@ * */ +#include <config.h> +#include "panoinc_WX.h" +#include "panoinc.h" + #include "PreviewDragTool.h" #include "CommandHistory.h" +#include "PT/PanoCommand.h" + #include <math.h> #include <GL/gl.h> @@ -47,13 +53,16 @@ // how far are we moving? if (drag_yaw || drag_pitch) { + /* TODO to the user, it would make more sense if the point they + * started dragging followed the mouse pointer. This doesn't work + * if the user drags from a point other than the centre. */ double yaw, pitch; helper->GetViewStatePtr()->GetProjectionInfo()->ImageToAngular(yaw, pitch, x, y); - shift_coordinates.x = yaw - start_coordinates.x; - shift_coordinates.y = start_coordinates.y - pitch; - if (!drag_yaw) shift_coordinates.x = 0.0; - if (!drag_pitch) shift_coordinates.y = 0.0; + shift_coordinates.x = yaw; + shift_coordinates.y = pitch; + if (!drag_yaw) shift_coordinates.x = start_coordinates.x; + if (!drag_pitch) shift_coordinates.y = start_coordinates.y; } if (drag_roll) { @@ -69,6 +78,7 @@ double new_yaw, new_pitch, new_roll; i->second.Move(shift_coordinates.x, shift_coordinates.y, shift_angle, + start_coordinates.x, start_coordinates.y, 0.0, new_yaw, new_pitch, new_roll); img.setYaw(new_yaw); img.setPitch(new_pitch); img.setRoll(new_roll); helper->GetViewStatePtr()->SetSrcImage(i->first, &img); @@ -125,21 +135,33 @@ hugin_utils::FDiff2D angular = helper->GetMousePosition() - centre; start_angle = atan2(angular.y, angular.x); shift_angle = 0.0; + // we'll always rotate around the centre of the panorama. + start_coordinates.x = 0.0; start_coordinates.y = 0.0; + shift_coordinates.x = 0.0; shift_coordinates.y = 0.0; } if (drag_yaw || drag_pitch) { + // We want to keep the point under the mouse pointer now under there + // wherever it goes. We'll calculate the roll, pitch, and yaw + // required to bring the centre to the point under the mouse. Then + // we rotate the panorama's images using the yaw and pitch of the + // movement. (Rotate start point to the centre, rotate by difference + // in yaw and pitch gained so far while dragging, then do the + // inverse of the rotation from start point to the centre on the + // result. // set angles + double yaw, pitch; hugin_utils::FDiff2D mouse_pos = helper->GetMousePosition(); - double yaw, pitch; helper->GetViewStatePtr()->GetProjectionInfo()->ImageToAngular(yaw, pitch, mouse_pos.x, mouse_pos.y); - start_coordinates.x = yaw; - start_coordinates.y = pitch; + start_coordinates.x = yaw; start_coordinates.y = pitch; + shift_coordinates.x = yaw; shift_coordinates.y = pitch; + // find the base transformation + base_rot[0] = yaw; base_rot[1] = pitch; base_rot[2] = 0.0; } if (drag_roll || drag_yaw || drag_pitch) { shift_angle = 0.0; - shift_coordinates.x = 0.0; shift_coordinates.y = 0.0; // record where the images are so we know what the difference is. // TODO use the topmost drawn component instead of all of the images /*std::set<unsigned int> dragging_images @@ -165,12 +187,18 @@ panorama.updateVariable( i, Variable("p", p) ); panorama.updateVariable( i, Variable("r", r) ); panorama.imageChanged(i);*/ - // TODO rotate the right stuff. + // TODO rotate the right stuff when not rotating the entire panorama. + // TODO use a single command, not two. GlobalCmdHist::getInstance().addCommand( new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), - shift_coordinates.x, shift_coordinates.y, - shift_angle) - ); + -start_coordinates.x, start_coordinates.y, + -shift_angle), + true); + GlobalCmdHist::getInstance().addCommand( + new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), + shift_coordinates.x, -shift_coordinates.y, + shift_angle), + true); // stop dragging image_angles.clear(); drag_yaw = false; drag_pitch = false; drag_roll = false; @@ -216,18 +244,30 @@ void PreviewDragTool::AngleStore::Move(double yaw_shift, double pitch_shift, double roll_shift, + double yaw_start, double pitch_start, + double roll_start, double &yaw_out, double &pitch_out, double &roll_out) { - // rotate the image around the centre point. - Matrix3 transform_matrix, original_matrix, output_matrix; - transform_matrix.SetRotationPT(DEG_TO_RAD(yaw_shift), - DEG_TO_RAD(pitch_shift), - DEG_TO_RAD(roll_shift)); + // rotate the start point to the centre + Matrix3 base_rot_matrix, shift_rot_matrix, base_rot_inverse_matrix, + original_matrix, output_matrix; original_matrix.SetRotationPT(DEG_TO_RAD(yaw), DEG_TO_RAD(pitch), DEG_TO_RAD(roll)); - output_matrix = transform_matrix * original_matrix; + base_rot_matrix.SetRotationPT(-DEG_TO_RAD(yaw_start), + DEG_TO_RAD(pitch_start), + -DEG_TO_RAD(roll_start)); + shift_rot_matrix.SetRotationPT(DEG_TO_RAD(yaw_shift), + -DEG_TO_RAD(pitch_shift), + DEG_TO_RAD(roll_shift)); + /*base_rot_inverse_matrix.SetRotationPT(-DEG_TO_RAD(yaw_start), + DEG_TO_RAD(pitch_start), + DEG_TO_RAD(roll_start));*/ + output_matrix = /*base_rot_inverse_matrix **/ base_rot_matrix * + shift_rot_matrix * original_matrix; + //output_matrix = shift_rot_matrix * original_matrix; + // collect the resultant rotations output_matrix.GetRotationPT(yaw_out, pitch_out, roll_out); yaw_out = RAD_TO_DEG(yaw_out); pitch_out = RAD_TO_DEG(pitch_out); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -60,14 +60,15 @@ double yaw, pitch, roll; void Set(HuginBase::SrcPanoImage *img); void Move(double yaw_shift, double pitch_shift, double roll_shift, + double yaw_start, double pitch_start, double roll_start, double &yaw_out, double &pitch_out, double &roll_out); }; private: std::map<unsigned int, AngleStore> image_angles; bool drag_yaw, drag_pitch, drag_roll; double start_angle, shift_angle; - hugin_utils::FDiff2D centre; - hugin_utils::FDiff2D start_coordinates, shift_coordinates; + hugin_utils::FDiff2D centre, start_coordinates, shift_coordinates; + double base_rot[3]; bool shift, control, alt; }; Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -0,0 +1,356 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewIdentifyTool.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "PreviewIdentifyTool.h" +#include <config.h> + +#include "panoinc_WX.h" + +#include "panoinc.h" + +#include "base_wx/platform.h" +#include "GLPreviewFrame.h" + +#include <GL/gl.h> +#include <GL/glu.h> + +#include <algorithm> +#include <vector> + +// the size of the rectangular texture. Must be a power of two, and at least 8. +#define rect_ts 64 +// the number of times larger the circular texture is, must be a power of 2, and +// at least 1. Making better improves the appearance of the circle. +#define circle_ts_multiple 4 +#define circle_ts (rect_ts * circle_ts_multiple) +#define circle_middle ((float) (circle_ts - 1) / 2.0) +#define circle_border_outer (circle_middle - 0.5 * (float) circle_ts_multiple) +#define circle_border_inner (circle_middle - 2.5 * (float) circle_ts_multiple) +#define circle_border_peak (circle_middle - 1.5 * (float) circle_ts_multiple) + +PreviewIdentifyTool::PreviewIdentifyTool(PreviewToolHelper *helper, + GLPreviewFrame *owner) + : PreviewTool(helper) +{ + preview_frame = owner; + // make the textures. We have a circle border and a square one. + // the textures are white with a the alpha chanel forming a border. + glGenTextures(1, &rectangle_border_tex); + glGenTextures(1, &circle_border_tex); + // we only want to specify alpha, but using just alpha in opengl attaches 0 + // for the luminosity. We'll bias rgb values to get 1.0, so we can colour + // the texture in something other than black: + glPixelTransferf(GL_RED_BIAS, 1.0); + glPixelTransferf(GL_GREEN_BIAS, 1.0); + glPixelTransferf(GL_BLUE_BIAS, 1.0); + { + // In the rectangle texture, the middle is 1/4 opaque, the outer pixels + // are completely transparent, and one pixel in from the edges is + // a completly opaque line. + unsigned char rect_tex_data[rect_ts][rect_ts]; + for (unsigned int x = 2; x < rect_ts-2; x++) + { + for (unsigned int y = 2; y < rect_ts - 2; y++) + { + rect_tex_data[x][y] = 63; + } + } + for (unsigned int d = 1; d < rect_ts - 1; d++) + { + rect_tex_data[d][1] = 255; + rect_tex_data[d][rect_ts - 2] = 255; + rect_tex_data[1][d] = 255; + rect_tex_data[rect_ts - 2][d] = 255; + } + for (unsigned int d = 0; d < rect_ts; d++) + { + rect_tex_data[d][0] = 0; + rect_tex_data[d][rect_ts - 1] = 0; + rect_tex_data[0][d] = 0; + rect_tex_data[rect_ts - 1][d] = 0; + } + glBindTexture(GL_TEXTURE_2D, rectangle_border_tex); + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, rect_ts, rect_ts, + GL_ALPHA, GL_UNSIGNED_BYTE, rect_tex_data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + } + { + // the circular one should look similar to the rectangle one, but we + // enlarge it so that the circle apears less blocky. We don't want to + // make it equally sharper however, so we make it a bit fuzzier by + // blending. + unsigned char circle_tex_data[circle_ts][circle_ts]; + for (unsigned int x = 0; x < circle_ts; x++) + { + for (unsigned int y = 0; y < circle_ts; y++) + { + float x_offs = (float) x - circle_middle, + y_offs = (float) y - circle_middle, + radius = sqrt(x_offs * x_offs + y_offs * y_offs), + intensity; + if (radius < circle_border_inner) + { + intensity = 63.0; + } else if (radius < circle_border_peak) + { + intensity = (radius - circle_border_inner) / + (float) circle_ts_multiple * 255.0 * 3.0 / 4.0 + 64.0; + } else if (radius < circle_border_outer) + { + intensity = (radius - circle_border_peak) / + (float) circle_ts_multiple * -255.0 + 256.0; + } else + { + intensity = 0.0; + } + circle_tex_data[x][y] = (unsigned char) intensity; + } + } + glBindTexture(GL_TEXTURE_2D, circle_border_tex); + gluBuild2DMipmaps(GL_TEXTURE_2D, + GL_LUMINANCE_ALPHA, circle_ts, circle_ts, + GL_ALPHA, GL_UNSIGNED_BYTE, circle_tex_data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + } + // set these back as expected. + glPixelTransferf(GL_RED_BIAS, 0.0); + glPixelTransferf(GL_GREEN_BIAS, 0.0); + glPixelTransferf(GL_BLUE_BIAS, 0.0); +} +PreviewIdentifyTool::~PreviewIdentifyTool() +{ + // free the textures + glDeleteTextures(1, &rectangle_border_tex); + glDeleteTextures(1, &circle_border_tex); +} + +void PreviewIdentifyTool::Activate() +{ + // register notifications + helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); + helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); + helper->NotifyMe(PreviewToolHelper::IMAGES_UNDER_MOUSE_CHANGE, this); + + // clear up + // Assume that there are no images under the mouse when the tool is + // activated. This should be fine if the user clicks the button to activate + // the tool. + image_set.clear(); + /* TODO if it becomes possible to activate the tool by a keyboard shortcut + * or something, call ImagesUnderMouseChangedEvent() to make sure we display + * indicators for images currently under the cursor. */ +} + +void PreviewIdentifyTool::ImagesUnderMouseChangedEvent() +{ + // If we are currently showing indicators for some of the images, we want + // to work out which ones are not in the new set, so we can set their + // buttons back to the system colour. + std::set<unsigned int> new_image_set = helper->GetImageNumbersUnderMouse(); + std::vector<unsigned int> difference(image_set.size()); + std::vector<unsigned int>::iterator end; + end = std::set_difference (image_set.begin(), image_set.end(), + new_image_set.begin(), new_image_set.end(), + difference.begin()); + DEBUG_ASSERT(end >= difference.begin() && end <= difference.end()); + std::vector<unsigned int>::iterator iterator; + if (iterator != end) + { + for (iterator = difference.begin(); iterator < end; iterator++) + { + DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages()); + // reset this button to its default system colour. + preview_frame->SetImageButtonColour(*iterator, 0, 0, 0); + // remove the notification + helper->DoNotNotifyMeBeforeDrawing(*iterator, this); + } + } + image_set.swap(new_image_set); + + // Redraw with new indicators. Since the indicators aren't part of the + // panorama and none of it is likely to change, we have to persuade the + // viewstate that a redraw is required. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); +} + +void PreviewIdentifyTool::AfterDrawImagesEvent() +{ + // we draw the partly transparent identification boxes over the top of the + // entire stack of images in image_set so that the extents of images in the + // background are clearly marked. + unsigned int num_images = image_set.size(); + // draw the actual images + std::set<unsigned int>::iterator it; + for (it = image_set.begin(); it != image_set.end(); it++) + { + DEBUG_ASSERT(*it < helper->GetPanoramaPtr()->getNrOfImages()); + helper->GetViewStatePtr()->GetTextureManager()-> + DrawImage(*it, + helper->GetViewStatePtr()->GetMeshDisplayList(*it)); + } + // now draw the identification boxes + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glMatrixMode(GL_TEXTURE); + unsigned int image_counter = 0; + for (it = image_set.begin(); it != image_set.end(); it++) + { + // we want to shift the texture so it lines up with the cropped region. + glPushMatrix(); + HuginBase::SrcPanoImage *src = helper->GetViewStatePtr()-> + GetSrcImage(*it); + int width = src->getSize().width(), height = src->getSize().height(); + vigra::Rect2D crop_region = src->getCropRect(); + // pick a texture depending on crop mode and move it to the cropped area + switch (src->getCropMode()) + { + case HuginBase::SrcPanoImage::CROP_CIRCLE: + glBindTexture(GL_TEXTURE_2D, circle_border_tex); + // change the crop region to a square around the circle. + if (crop_region.width() < crop_region.height()) + { + // too tall, move top and bottom. + int diff = (crop_region.width() - crop_region.height()) / 2; + // diff is negative, so we will shrink the border in the y + // direction. + crop_region.addBorder(0, diff); + } else if (crop_region.width() > crop_region.height()) + { + // too wide, move left and right + int diff = (crop_region.height() - crop_region.width()) / 2; + crop_region.addBorder(diff, 0); + } + { + float diameter = (float) crop_region.width(); + glScalef((float) width / diameter, + (float) height / diameter, 1.0); + glTranslatef(-(float) crop_region.left() / (float) width, + -(float) crop_region.top() / (float) height, + 0.0); + } + break; + case HuginBase::SrcPanoImage::CROP_RECTANGLE: + // get the biggest rectangle contained by both the image + // and the cropped area. + crop_region &= vigra::Rect2D(src->getSize()); + glBindTexture(GL_TEXTURE_2D, rectangle_border_tex); + glScalef((float) width / (float) crop_region.width(), + (float) height / (float) crop_region.height(), + 1.0); + glTranslatef(-(float) crop_region.left() / (float) width, + -(float) crop_region.top() / (float) height, + 0.0); + break; + case HuginBase::SrcPanoImage::NO_CROP: + glBindTexture(GL_TEXTURE_2D, rectangle_border_tex); + break; + } + // draw the image in this texture + unsigned char r,g,b; + HighlightColour(image_counter, num_images, r, g, b); + image_counter++; + glColor3ub(r,g,b); + glCallList(helper->GetViewStatePtr()->GetMeshDisplayList(*it)); + glPopMatrix(); + // tell the preview frame to update the button to show the same colour. + preview_frame->SetImageButtonColour(*it, r, g, b); + } + // set stuff back how we found it. + glMatrixMode(GL_MODELVIEW); + glDisable(GL_BLEND); + glColor3ub(255, 255, 255); +} + +bool PreviewIdentifyTool::BeforeDrawImageNumber(unsigned int image) +{ + // Delay drawing of images, so we can show them on top of the others. + DEBUG_ASSERT(image < helper->GetPanoramaPtr()->getNrOfImages()); + if (image_set.count(image)) return false; + return true; +} + +void PreviewIdentifyTool::ShowImageNumber(unsigned int image) +{ + DEBUG_ASSERT(image < helper->GetPanoramaPtr()->getNrOfImages()); + // Add this image to the set of images drawn. + image_set.insert(image); + // now we want a redraw. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); +} + +void PreviewIdentifyTool::StopShowingImages() +{ + // set the colour to the image the user just moused off to the default. + preview_frame->SetImageButtonColour(*image_set.begin(), 0, 0, 0); + image_set.clear(); + // now redraw without the indicator. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); +} + +// generate a colour given how many colours we need and an index. +void PreviewIdentifyTool::HighlightColour(unsigned int index, + unsigned int count, + unsigned char &red, + unsigned char &green, + unsigned char &blue) +{ + DEBUG_ASSERT(index < count && index >= 0); + // the first one is red, the rest are evenly spaced throughout the spectrum + float hue = ((float) index / (float) count) * 6.0; + if (hue < 1.0) + { + // red to yellow + red = 255; + green = (unsigned char) (hue * 255.0); + blue = 0; + } else if (hue < 2.0) { + // yellow to green + red = (unsigned char) ((-hue + 2.0) * 255.0); + green = 255; + blue = 0; + } else if (hue < 3.0) { + // green to cyan + red = 0; + green = 255; + blue = (unsigned char) ((hue - 2.0) * 255.0); + } else if (hue < 4.0) { + // cyan to blue + red = 0; + green = (unsigned char) ((-hue + 4.0) * 255.0); + blue = 255; + } else if (hue < 5.0) { + // blue to magenta + red = (unsigned char) ((hue - 4.0) * 255.0); + green = 0; + blue = 255; + } else { + // magenta to red + red = 255; + green = 0; + blue = (unsigned char) ((-hue + 6.0) * 255.0); + } +} + Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -0,0 +1,65 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewIdentifyTool.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* The PreviewIdentifyTool connects the image numbers with the image on the + * preview. There are two ways it does this: + * 1. When the user moves the mouse pointer over a image button, the image is + * highlighted in the preview. + * 2. When the user moves the mouse pointer over the preview, the image under + * the pointer are highlighted with matching colours over the buttons. + * The "highlighted" images are drawn on top of the other images, with a + * coloured border. + */ + +#ifndef _PREVIEWIDENTIFYTOOL_H +#define _PREVIEWIDENTIFYTOOL_H + +#include "PreviewTool.h" +#include <set> + +class GLPreviewFrame; + +class PreviewIdentifyTool : public PreviewTool +{ +public: + PreviewIdentifyTool(PreviewToolHelper *helper, GLPreviewFrame *owner); + ~PreviewIdentifyTool(); + void Activate(); + void ImagesUnderMouseChangedEvent(); + void AfterDrawImagesEvent(); + bool BeforeDrawImageNumber(unsigned int image); + // these are called when the user moves the mouse over the image buttons. + void ShowImageNumber(unsigned int image); // mouse on + void StopShowingImages(); // mouse off +private: + // generate a colour given how many colours we need and an index. + void HighlightColour(unsigned int index, unsigned int count, + unsigned char &red, unsigned char &green, + unsigned char &blue); + // the OpenGL texture name for the two borders: + unsigned int circle_border_tex, rectangle_border_tex; + // the set of image numbers of the images we are displaying. + std::set<unsigned int> image_set; + GLPreviewFrame *preview_frame; +}; + +#endif + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -41,13 +41,16 @@ /* When the user switches on the tool, Activate is called. We should * register events we want to respond to with the helper when activating, - * these are lost when the tool is deactivated, but we are not notified. */ + * these are lost when the tool is deactivated, but we are not notified of + * this. Activate will be called again if the tool is reactivated, we should + * clean up anything we need to from the previous use here. */ virtual void Activate() = 0; // These are called when events happen, providing we requested notification. // The coordinates are in the space of the panorama output at full size. virtual void MouseMoveEvent(double x, double y) {} virtual void MouseButtonEvent(wxMouseEvent &e) {} + virtual void ImagesUnderMouseChangedEvent() {} virtual void KeypressEvent(int keycode, int modifiers, bool pressed) {} // In the next few events we are free to draw stuff in OpenGL. virtual void BeforeDrawImagesEvent() {} Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -24,6 +24,7 @@ #include "PreviewToolHelper.h" #include "PreviewTool.h" + PreviewToolHelper::PreviewToolHelper(PT::Panorama *pano_in, ViewState *view_state_in) { @@ -72,7 +73,31 @@ (*iterator)->MouseMoveEvent(mouse_x, mouse_y); } // If the mouse has moved, then we don't know what is underneath it anoymore + InvalidateImagesUnderMouse(); +} + +void PreviewToolHelper::InvalidateImagesUnderMouse() +{ images_under_mouse_current = false; + // if there are tools that want to know when the images under the mouse + // pointer change, we better detect the images and notfiy them is applicable + if (!images_under_mouse_notified_tools.empty()) + { + // there are tools that want to know... so find out: + std::set<unsigned int> old_images_under_mouse = images_under_mouse; + UpdateImagesUnderMouse(); + if (old_images_under_mouse != images_under_mouse) + { + // The list has changed. Notifiy all tools that requested it. + std::set<PreviewTool *>::iterator iterator; + for (iterator = images_under_mouse_notified_tools.begin(); + iterator != images_under_mouse_notified_tools.end(); + iterator++) + { + (*iterator)->ImagesUnderMouseChangedEvent(); + } + } + } } void PreviewToolHelper::MouseButtonEvent(wxMouseEvent &e) @@ -102,7 +127,7 @@ (*iterator)->BeforeDrawImagesEvent(); } // Since we are drawing a new frame, lets assume something has changed. - images_under_mouse_current = false; + InvalidateImagesUnderMouse(); } void PreviewToolHelper::AfterDrawImages() @@ -182,6 +207,9 @@ case DRAW_OVER_IMAGES: AddTool(tool, &draw_over_notified_tools); break; + case IMAGES_UNDER_MOUSE_CHANGE: + AddTool(tool, &images_under_mouse_notified_tools); + break; } } @@ -218,6 +246,9 @@ case DRAW_OVER_IMAGES: RemoveTool(tool, &draw_over_notified_tools); break; + case IMAGES_UNDER_MOUSE_CHANGE: + RemoveTool(tool, &images_under_mouse_notified_tools); + break; } } @@ -272,9 +303,12 @@ std::vector<PreviewTool *> *vector, unsigned int index) { - if ((*vector)[index] == tool) + if ((*vector).size() > index) { - (*vector)[index] = 0; + if ((*vector)[index] == tool) + { + (*vector)[index] = 0; + } } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -24,6 +24,7 @@ * and guides the interaction between tools. These features are available: * - Notification of user events: * - When the mouse moves + * - When the set of images under the mouse pointer changes * - When the mouse button is pressed / released. * - When a key is pressed / released * - Notifications when drawing things on the preview, allowing: @@ -32,10 +33,6 @@ * - Replacing or stopping the drawing of each individual image. * - Notification of when: * - The tool is activated. - * - The tool is deactivated. - * - The tool has to give up some event notifications. - * (when another tool requests them, we don't want two different things - * responding to the same mouse click for example) * - The tool can request the mouse position. * - The tool can request a list of images under the mouse. * - The tool can access the panorama, and make changes to it. @@ -58,7 +55,7 @@ #include <hugin_math/hugin_math.h> #include "ViewState.h" -#include "panoinc.h" +#include "PT/Panorama.h" class PreviewTool; @@ -69,6 +66,7 @@ { MOUSE_MOVE, MOUSE_PRESS, KEY_PRESS, DRAW_UNDER_IMAGES, DRAW_OVER_IMAGES, + IMAGES_UNDER_MOUSE_CHANGE }; PreviewToolHelper(PT::Panorama *pano, ViewState *view_state); @@ -118,6 +116,7 @@ PreviewTool * keypress_notified_tool; std::set<PreviewTool *> draw_under_notified_tools; std::set<PreviewTool *> draw_over_notified_tools; + std::set<PreviewTool *> images_under_mouse_notified_tools; // these are vectors: the index is the image that a single tool uses. std::vector<PreviewTool *> image_draw_begin_tools; std::vector<PreviewTool *> image_draw_end_tools; @@ -132,10 +131,13 @@ void AddTool(PreviewTool *tool, std::set<PreviewTool *> *set); void AddTool(PreviewTool *tool, std::vector<PreviewTool *> *vector, unsigned int index); + // is the set of images under the mouse up to date? bool images_under_mouse_current; + // which images are under the mouse? std::set<unsigned int> images_under_mouse; void UpdateImagesUnderMouse(); + void InvalidateImagesUnderMouse(); }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -23,10 +23,11 @@ #include "TexCoordRemapper.h" #include "algorithms/nona/ComputeImageROI.h" #include "ViewState.h" -#include <cstdlib> // higher values make the mesh more detailed, but slower and using more memory: -const double mesh_frequency = 0.0884; +// Value is in faces per pixel in each direction, so it should be positive and +// less than 1. Faces will be around this size, approximately square. +const double mesh_frequency = 0.07; TexCoordRemapper::TexCoordRemapper(HuginBase::Panorama *m_pano, unsigned int image_number, @@ -50,13 +51,13 @@ { for (unsigned int y = 0; y < divisions_y; y++) { - transform.transformImgCoord(map[x][y].first, - map[x][y].second, + transform.transformImgCoord(map[x][y].x, + map[x][y].y, (double) x * face_width + start_x, (double) y * face_height + start_y); // texture coordinates on the image range from 0 to 1. - map[x][y].first /= width; - map[x][y].second /= height; + map[x][y].x /= width; + map[x][y].y /= height; } } face_index = 0; @@ -82,10 +83,10 @@ for (unsigned short int y = 0; y < 2; y++) { unsigned int xt = x_f + x, yt = y_f + y; - if (map[xt][yt].first > crop_x1) all_left = false; - if (map[xt][yt].first < crop_x2) all_right = false; - if (map[xt][yt].second > crop_y1) all_above = false; - if (map[xt][yt].second < crop_y2) all_below = false; + if (map[xt][yt].x > crop_x1) all_left = false; + if (map[xt][yt].x < crop_x2) all_right = false; + if (map[xt][yt].y > crop_y1) all_above = false; + if (map[xt][yt].y < crop_y2) all_below = false; } } /* check if this quad shows any of the input image. @@ -103,8 +104,8 @@ for (unsigned short int y = 0; y < 2; y++) { unsigned int xt = x_f + x, yt = y_f + y; - result->tex_c[x][y][0] = map[xt][yt].first; - result->tex_c[x][y][1] = map[xt][yt].second; + result->tex_c[x][y][0] = map[xt][yt].x; + result->tex_c[x][y][1] = map[xt][yt].y; result->vertex_c[x][y][0] = (double) xt * face_width + start_x; result->vertex_c[x][y][1] = (double) yt * face_height + start_y; } @@ -126,6 +127,9 @@ int(result->tex_c[1][1][1] * height)))) { // all inside, doesn't need clipping. + /* FIXME Alber's equal area conic projection needs to be clipped to the + * sides space in the output that maps to the panorama... + */ return true; } /* We have to clip the face to the source image. This may produce many faces Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TexCoordRemapper.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -32,6 +32,8 @@ #define __TEXCOORDREMAPPER_H #include "MeshRemapper.h" +#include <vector> +#include "hugin_math/hugin_math.h" class TexCoordRemapper: public MeshRemapper { @@ -44,7 +46,7 @@ void SetSize(); // this stores all the coordinates, and can return rows of them. // arrays don't meet the requirements for std::vector, so we use a pair. - std::vector< std::vector< std::pair<double, double> > > map; + std::vector< std::vector<hugin_utils::FDiff2D> > map; // dimensions for the area we cover. This can be used for clipping. double start_x, start_y, end_x, end_y; // this is the number of vertices we use in each direction. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -34,8 +34,8 @@ #include <GL/glu.h> #include <config.h> -#include "panoinc_WX.h" -#include "panoinc.h" +//#include "panoinc_WX.h" +//#include "panoinc.h" #include "ViewState.h" #include "TextureManager.h" @@ -43,14 +43,13 @@ #include "vigra/stdimage.hxx" #include "vigra/resizeimage.hxx" #include "vigra/impex.hxx" -#include <vigra_ext/Pyramid.h> +//#include <vigra_ext/Pyramid.h> #include "base_wx/ImageCache.h" -#include "photometric/ResponseTransform.h" +#include "photometric/ResponseTransform.h" - -TextureManager::TextureManager(PT::Panorama &pano, ViewState *view_state_in) +TextureManager::TextureManager(PT::Panorama *pano, ViewState *view_state_in) { - m_pano = &pano; + m_pano = pano; photometric_correct = false; view_state = view_state_in; } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-08-01 03:43:35 UTC (rev 3258) @@ -40,6 +40,7 @@ #include <string> #include <map> +#include "PT/Panorama.h" class GLViewer; class ViewState; @@ -47,7 +48,7 @@ class TextureManager { public: - TextureManager(PT::Panorama &pano, ViewState *view); + TextureManager(PT::Panorama *pano, ViewState *view); virtual ~TextureManager(); // selct the texture for the requested image in opengl void DrawImage(unsigned int image_number, unsigned int display_list); @@ -57,8 +58,10 @@ // change the OpenGL state for rendering the textures. void Begin(); void End(); - // set to true if we aer doing photmetric correction + // set to true if we are doing photmetric correction void SetPhotometricCorrect(bool state); + // return true if we are doing photometric correction. + bool GetPhotometricCorrect() {return photometric_correct;} protected: PT::Panorama * m_pano; ViewState *view_state; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-07-31 21:25:05 UTC (rev 3257) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-01 03:43:35 UTC (rev 3258) @@ -75,10 +75,10 @@ // this is the length in screen pixels under which no subdivision occurs. // higher values are faster, lower ones more accurate. // TODO user preference? Increase during interactive changes? -const double min_length = 4.0; +const double min_length = 14.0; // the angle in radians under which no subdivision occurs. Again, higher values // will make it faster, lower ones will give higher accuracy. must be positive. -const double min_angle = 0.05; +const double min_angle = 0.06; // the distance in absolute screen pixels between twice the length of the // children and the length of the parent nodes, under which no subdivision // occurs. higher values are faster, lower values give higher accuracy. Must be @@ -1110,6 +1110,9 @@ // if any of the vertices we are want to use are invalid (e.g. behind the // viewer in a rectilinear projection) we don't want to risk using them: if (nodes[node_id].flags & (transform_fail_flag * 15)) return 0; + // if this face crosses a discontinuity, we should be using a point off + // screen instead of in the middle. Refuse to use these faces + if (nodes[node_id].flags & (vertex_side_flag_start * 15)) return 0; // linearly interpolate the node's corners. // most of the time we only use factors of 0 and 1, we don't want to make // points up except ... [truncated message content] |
From: <jl...@us...> - 2008-08-05 17:57:54
|
Revision: 3273 http://hugin.svn.sourceforge.net/hugin/?rev=3273&view=rev Author: jlegg Date: 2008-08-05 17:57:49 +0000 (Tue, 05 Aug 2008) Log Message: ----------- Fixed the point to point dragging of the drag tool. Changed modifier keys for the drag tool so that shift now constrains the direction to either yaw or pitch (from the point dragged), picking whichever movement is bigger. This is a little confusing under some projections (yaw and pitch are curved through the output projection) so the preview draws lines to help. The Identification tool now shows image indicators when the mouse is moved over image's show/hide toggle buttons correctly. Removed a couple of assertions in computing intersections for polygon clipping. When they were triggered I didn't think clipping would work, but I haven't an example of anywhere it causes noticable mistakes. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -111,7 +111,7 @@ if (selected_remapper) { delete selected_remapper; - selected_remapper = NULL; + selected_remapper = 0; } selected_remapper = new TexCoordRemapper(m_pano, image_number, @@ -130,7 +130,7 @@ if (selected_remapper) { delete selected_remapper; - selected_remapper = NULL; + selected_remapper = 0; } selected_remapper = new VertexCoordRemapper(m_pano, image_number, Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -75,7 +75,8 @@ ID_TOGGLE_BUT = wxID_HIGHEST+500, PROJ_PARAM_NAMES_ID = wxID_HIGHEST+1300, PROJ_PARAM_VAL_ID = wxID_HIGHEST+1400, - PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1500 + PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1500, + ID_TOGGLE_BUT_LEAVE = wxID_HIGHEST+1600 }; BEGIN_EVENT_TABLE(GLPreviewFrame, wxFrame) @@ -99,19 +100,20 @@ EVT_CHOICE(ID_BLEND_CHOICE, GLPreviewFrame::OnBlendChoice) EVT_CHOICE(ID_PROJECTION_CHOICE, GLPreviewFrame::OnProjectionChoice) EVT_CHOICE(ID_OUTPUTMODE_CHOICE, GLPreviewFrame::OnOutputChoice) -#ifdef USE_TOGGLE_BUTTON - EVT_TOGGLEBUTTON(-1, GLPreviewFrame::OnChangeDisplayedImgs) -#else - EVT_CHECKBOX(-1, GLPreviewFrame::OnChangeDisplayedImgs) -#endif - //EVT_ENTER_WINDOW(-1, GLPreviewFrame::MouseEnter) - EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV) -// EVT_SCROLL_THUMBRELEASE(GLPreviewFrame::OnChangeFOV) -// EVT_SCROLL_ENDSCROLL(GLPreviewFrame::OnChangeFOV) EVT_SCROLL_THUMBTRACK(GLPreviewFrame::OnTrackChangeFOV) END_EVENT_TABLE() +BEGIN_EVENT_TABLE(ImageToogleButtonEventHandler, wxEvtHandler) + EVT_ENTER_WINDOW(ImageToogleButtonEventHandler::OnEnter) + EVT_LEAVE_WINDOW(ImageToogleButtonEventHandler::OnLeave) +#ifdef USE_TOGGLE_BUTTON + EVT_TOGGLEBUTTON(-1, ImageToogleButtonEventHandler::OnChange) +#else + EVT_CHECKBOX(-1, ImageToogleButtonEventHandler::OnChange) +#endif +END_EVENT_TABLE() + #define PF_STYLE (wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN) #include <iostream> GLPreviewFrame::GLPreviewFrame(wxFrame * frame, PT::Panorama &pano) @@ -363,7 +365,7 @@ CreateStatusBar(3); int widths[3] = {-3, 150, 150}; SetStatusWidths(3, widths); - SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0); + // SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0); SetStatusText(wxT(""),1); SetStatusText(wxT(""),2); @@ -381,7 +383,7 @@ m_pano.addObserver(this); - RestoreFramePosition(this, wxT("PreviewFrame")); + RestoreFramePosition(this, wxT("GLPreviewFrame")); // TODO tell renderer // m_PreviewPanel->SetBlendMode((PreviewPanel::BlendMode)oldMode ); @@ -391,7 +393,7 @@ this->SetBackgroundColour(m_GLViewer->GetBackgroundColour()); #endif - if (config->Read(wxT("/PreviewFrame/isShown"), 0l) != 0) { + if (config->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0) { Show(); } SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0); @@ -403,40 +405,19 @@ wxConfigBase * config = wxConfigBase::Get(); wxSize sz = GetClientSize(); - StoreFramePosition(this, wxT("PreviewFrame")); + StoreFramePosition(this, wxT("GLPreviewFrame")); if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) { - config->Write(wxT("/PreviewFrame/isShown"), 1l); + config->Write(wxT("/GLPreviewFrame/isShown"), 1l); } else { - config->Write(wxT("/PreviewFrame/isShown"), 0l); + config->Write(wxT("/GLPreviewFrame/isShown"), 0l); } - config->Write(wxT("/PreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); + config->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); m_pano.removeObserver(this); DEBUG_TRACE("dtor end"); } -void GLPreviewFrame::OnChangeDisplayedImgs(wxCommandEvent & e) -{ - int id = e.GetId() - ID_TOGGLE_BUT; - int nImg = m_pano.getNrOfImages(); - UIntSet activeImages = m_pano.getActiveImages(); - DEBUG_DEBUG("toggle_button_id: " << id << " nImg:" << nImg << " m_ToggleButtons.size(): " << m_ToggleButtons.size()); - if (id >= 0 && id < nImg) { - if (e.IsChecked()) { - activeImages.insert(id); - } else { - activeImages.erase(id); - } -// m_PreviewPanel->SetDisplayedImages(m_displayedImgs); - GlobalCmdHist::getInstance().addCommand( - new PT::SetActiveImagesCmd(m_pano, activeImages) - ); - } else { - // FIXME DEBUG_ERROR("invalid Togglebutton ID"); - } -} - void GLPreviewFrame::panoramaChanged(Panorama &pano) { const PanoramaOptions & opts = pano.getOptions(); @@ -538,6 +519,8 @@ m_ButtonSizer->Detach(m_ToggleButtons[i]); delete m_ToggleButtons[i]; m_ToggleButtons.pop_back(); + delete toogle_button_event_handlers[i]; + toogle_button_event_handlers.pop_back(); dirty = true; } @@ -561,6 +544,15 @@ #endif wxFileName tFilename(wxString (pano.getImage(imgNr).getFilename().c_str(), HUGIN_CONV_FILENAME)); but->SetToolTip(tFilename.GetFullName()); + // for the identification tool to work, we need to find when the + // mouse enters and exits the button. We use a custom event + // handler, which will also toggle the images: + ImageToogleButtonEventHandler * event_handler = new + ImageToogleButtonEventHandler(*it, &identify_tool, + identify_tool_id, m_ToolBar, + &m_pano); + toogle_button_event_handlers.push_back(event_handler); + but->PushEventHandler(event_handler); wxSize sz = but->GetSize(); // but->SetSize(res.GetWidth(),sz.GetHeight()); // HACK.. set fixed width. that should work @@ -1074,3 +1066,65 @@ } } +ImageToogleButtonEventHandler::ImageToogleButtonEventHandler( + unsigned int image_number_in, + PreviewIdentifyTool **identify_tool_in, + unsigned int identify_tool_id_in, + wxToolBar *tool_bar_in, + PT::Panorama * m_pano_in) +{ + image_number = image_number_in; + identify_tool = identify_tool_in; + identify_tool_id = identify_tool_id_in; + tool_bar = tool_bar_in; + m_pano = m_pano_in; +} + +void ImageToogleButtonEventHandler::OnEnter(wxMouseEvent & e) +{ + // When using the identify tool, we want to identify image locations when + // the user moves the mouse over the image buttons, but only if the image + // is being shown. + if ( tool_bar->GetToolState(identify_tool_id) + && m_pano->getActiveImages().count(image_number)) + { + (*identify_tool)->ShowImageNumber(image_number); + } + e.Skip(); +} + +void ImageToogleButtonEventHandler::OnLeave(wxMouseEvent & e) +{ + // if the mouse left one of the image toggle buttons with the identification + // tool active, we should stop showing the image indicator for that button. + if (tool_bar->GetToolState(identify_tool_id) + && m_pano->getActiveImages().count(image_number)) + { + (*identify_tool)->StopShowingImages(); + } + e.Skip(); +} + +void ImageToogleButtonEventHandler::OnChange(wxCommandEvent & e) +{ + // the user is turning on or off an image using its button. We want to turn + // the indicators on and off if appropriate correctly to. We use OnEnter + // and OnLeave for the indicators, but these only work when the image is + // showing, so we are carefull of the order: + UIntSet activeImages = m_pano->getActiveImages(); + wxMouseEvent null_event; + if (e.IsChecked()) { + activeImages.insert(image_number); + GlobalCmdHist::getInstance().addCommand( + new PT::SetActiveImagesCmd(*m_pano, activeImages) + ); + OnEnter(null_event); + } else { + OnLeave(null_event); + activeImages.erase(image_number); + GlobalCmdHist::getInstance().addCommand( + new PT::SetActiveImagesCmd(*m_pano, activeImages) + ); + } +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -34,6 +34,30 @@ class PreviewDragTool; class PreviewIdentifyTool; +// the image toggle buttons need a special event handler to trap mouse enter and +// leave events. + +class ImageToogleButtonEventHandler : public wxEvtHandler +{ +public: + ImageToogleButtonEventHandler(unsigned int image_number, + PreviewIdentifyTool **identify_tool, + unsigned int identify_tool_id, + wxToolBar *tool_bar, + PT::Panorama * m_pano); + void OnChange(wxCommandEvent &e); +protected: + void OnEnter(wxMouseEvent & e); + void OnLeave(wxMouseEvent & e); +private: + DECLARE_EVENT_TABLE() + unsigned int image_number; + PreviewIdentifyTool **identify_tool; + unsigned int identify_tool_id; + wxToolBar *tool_bar; + PT::Panorama * m_pano; +}; + /** The OpenGL preview frame * * Contains the GLViewer and various controls for it. @@ -64,7 +88,6 @@ protected: void OnClose(wxCloseEvent& e); - void OnChangeDisplayedImgs(wxCommandEvent & e); void OnCenterHorizontally(wxCommandEvent & e); void OnFitPano(wxCommandEvent& e); void OnStraighten(wxCommandEvent & e); @@ -123,7 +146,7 @@ #else std::vector<wxCheckBox *> m_ToggleButtons; #endif - + std::vector<ImageToogleButtonEventHandler *> toogle_button_event_handlers; DECLARE_EVENT_TABLE() // tools @@ -136,5 +159,4 @@ }; - #endif // _GLPREVIEWFRAME_H Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -40,6 +40,8 @@ EVT_SIZE (GLViewer::Resized) // mouse motion EVT_MOTION (GLViewer::MouseMotion) + // mouse entered or left the preview + EVT_LEAVE_WINDOW(GLViewer::MouseLeave) // mouse buttons EVT_LEFT_DOWN (GLViewer::LeftDown) EVT_LEFT_UP (GLViewer::LeftUp) @@ -183,6 +185,11 @@ (int) e.m_y - offset.y); } +void GLViewer::MouseLeave(wxMouseEvent & e) +{ + m_tool_helper->MouseLeave(); +} + void GLViewer::LeftDown(wxMouseEvent& e) { m_tool_helper->MouseButtonEvent(e); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -50,6 +50,7 @@ ViewState * m_view_state; protected: void MouseMotion(wxMouseEvent& e); + void MouseLeave(wxMouseEvent & e); void LeftDown(wxMouseEvent& e); void LeftUp(wxMouseEvent& e); void RightDown(wxMouseEvent& e); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -162,7 +162,6 @@ const unsigned int v2_index, const double cl[3]) const { - DEBUG_ASSERT(Inside(v1_index, cl) != Inside(v2_index, cl)); // find the point of intersection from the given edge with a clip plane. // the edge is the vertex with the same number and the one before it. // Get pointers to the vertecies we will use @@ -182,7 +181,8 @@ // t * (cl[0] * dx + cl[1] * dy) + cl[0] * v1_x + cl[1] * v1_y + cl[2] = 0 // t * (cl[0] * dx + cl[1] * dy) = -cl[0] * v1_x - cl[1] * v1_y - cl[2] // so we get: - /* FIXME this assertion sometimes fails. t should always be between 0 and 1. + /* FIXME this assertion sometimes fails. t should always be between 0 and 1, + * but sometimes isn't even when this one passes: */ DEBUG_ASSERT(cl[0] * dx + cl[1] * dy); double t = (-cl[0] * v1->tex_c[0] - cl[1] * v1->tex_c[1] - cl[2]) / @@ -195,7 +195,7 @@ td1 = 1.0 - t, xc = v1->vertex_c[0] * td1 + v2->vertex_c[0] * t, yc = v1->vertex_c[1] * td1 + v2->vertex_c[1] * t; - DEBUG_ASSERT(0.0 <= t && t <= 1.0); + // DEBUG_ASSERT(-0.1 <= t && t <= 1.1); return Vertex(xc, yc, x, y); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -38,11 +38,10 @@ void PreviewDragTool::Activate() { drag_yaw = false; drag_pitch = false; drag_roll = false; - shift = false; control = false; alt = false; + shift = false; control = false; // register notifications helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); - helper->NotifyMe(PreviewToolHelper::KEY_PRESS, this); helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); } @@ -53,33 +52,39 @@ // how far are we moving? if (drag_yaw || drag_pitch) { - /* TODO to the user, it would make more sense if the point they - * started dragging followed the mouse pointer. This doesn't work - * if the user drags from a point other than the centre. */ + double yaw, pitch; helper->GetViewStatePtr()->GetProjectionInfo()->ImageToAngular(yaw, pitch, x, y); shift_coordinates.x = yaw; shift_coordinates.y = pitch; - if (!drag_yaw) shift_coordinates.x = start_coordinates.x; - if (!drag_pitch) shift_coordinates.y = start_coordinates.y; + if (shift) + { + if (abs(shift_coordinates.x - start_coordinates.x) + < abs(shift_coordinates.y - start_coordinates.y)) + { + shift_coordinates.x = start_coordinates.x; + } else { + shift_coordinates.y = start_coordinates.y; + } + } } if (drag_roll) { - shift_angle = RAD_TO_DEG(atan2(y - centre.y, x- centre.x) - - start_angle); + shift_angle = atan2(y - centre.y, x- centre.x) - start_angle; } // move the selected images on the tempory copies for display. + // first calculate a matrix representing the transformation + SetRotationMatrix(shift_coordinates.x, shift_coordinates.y, shift_angle, + start_coordinates.x, start_coordinates.y, 0.0); + // now transform the images in the ViewState (not the panorama yet) std::map<unsigned int, AngleStore>::iterator i; for (i = image_angles.begin(); i != image_angles.end(); i++ ) { HuginBase::SrcPanoImage img = *helper->GetViewStatePtr()-> GetSrcImage(i->first); double new_yaw, new_pitch, new_roll; - i->second.Move(shift_coordinates.x, shift_coordinates.y, - shift_angle, - start_coordinates.x, start_coordinates.y, 0.0, - new_yaw, new_pitch, new_roll); + i->second.Move(&rotation_matrix, new_yaw, new_pitch, new_roll); img.setYaw(new_yaw); img.setPitch(new_pitch); img.setRoll(new_roll); helper->GetViewStatePtr()->SetSrcImage(i->first, &img); } @@ -92,7 +97,6 @@ { if (e.ButtonDown()) { - alt = e.m_altDown | e.m_metaDown; control = e.m_controlDown; shift = e.m_shiftDown; switch (e.GetButton()) @@ -100,38 +104,27 @@ // primary button case wxMOUSE_BTN_LEFT: // different things depending on modifier keys. - if (!(alt || shift || control)) + if (!control) { - // no keys + // Either no key modifiers we care about, or shift. + // With shift we determine an adaptive constraint based on + // movement in both directions. drag_yaw = true; drag_pitch = true; } - else if (shift && !(control || alt)) + else if (control && !(shift)) { - drag_pitch = true; - } - else if (control && !(alt || shift)) - { drag_roll = true; } - else if (alt && !(control || shift)) - { - drag_yaw = true; - } break; case wxMOUSE_BTN_RIGHT: - if (!(alt || shift || control)) - { - drag_roll = true; - } + drag_roll = true; break; } if (drag_roll) { // set centre and angle - HuginBase::PanoramaOptions *opts - = helper->GetViewStatePtr()->GetOptions(); - centre.x = double (opts->getSize().width()) / 2.0; - centre.y = double (opts->getSize().height()) / 2.0; + helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage( + centre.x, centre.y, 0.0, 0.0); hugin_utils::FDiff2D angular = helper->GetMousePosition() - centre; start_angle = atan2(angular.y, angular.x); shift_angle = 0.0; @@ -156,8 +149,6 @@ pitch, mouse_pos.x, mouse_pos.y); start_coordinates.x = yaw; start_coordinates.y = pitch; shift_coordinates.x = yaw; shift_coordinates.y = pitch; - // find the base transformation - base_rot[0] = yaw; base_rot[1] = pitch; base_rot[2] = 0.0; } if (drag_roll || drag_yaw || drag_pitch) { @@ -177,7 +168,10 @@ for (unsigned int i = 0; i < imgs; i++) { image_angles[i].Set(helper->GetViewStatePtr()->GetSrcImage(i)); - } + }; + SetRotationMatrix(shift_coordinates.x, shift_coordinates.y, + shift_angle, + start_coordinates.x, start_coordinates.y, 0.0); } } else { // apply rotations permanently @@ -188,30 +182,20 @@ panorama.updateVariable( i, Variable("r", r) ); panorama.imageChanged(i);*/ // TODO rotate the right stuff when not rotating the entire panorama. - // TODO use a single command, not two. + double yaw, pitch, roll; + rotation_matrix.GetRotationPT(yaw, pitch, roll); + yaw = RAD_TO_DEG(yaw); + pitch = RAD_TO_DEG(pitch); + roll = RAD_TO_DEG(roll); GlobalCmdHist::getInstance().addCommand( new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), - -start_coordinates.x, start_coordinates.y, - -shift_angle), - true); - GlobalCmdHist::getInstance().addCommand( - new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), - shift_coordinates.x, -shift_coordinates.y, - shift_angle), - true); + yaw, pitch, roll), true); // stop dragging image_angles.clear(); drag_yaw = false; drag_pitch = false; drag_roll = false; } } -void PreviewDragTool::KeypressEvent(int keycode, int modifiers, bool pressed) -{ - alt = modifiers & (wxMOD_ALT | wxMOD_META); - shift = modifiers & wxMOD_SHIFT; - control = modifiers & wxMOD_CONTROL; -} - void PreviewDragTool::AfterDrawImagesEvent() { // draw guide lines down the middle. @@ -220,17 +204,56 @@ height = (double) opts->getSize().height(); // Invert the color underneath. glDisable(GL_TEXTURE_2D); - glPushMatrix(); - glTranslatef(-0.5, -0.5, -0.5); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + glEnable(GL_BLEND); glColor3f(1.0, 1.0, 1.0); + glPushMatrix(); + glTranslatef(-0.5, -0.5, -0.5); glBegin(GL_LINES); glVertex2f(width / 2.0, 0.0); glVertex2f(width / 2.0, height); glVertex2f(0.0, height / 2.0); - glVertex2f(width, height / 2.0); + glVertex2f(width, height / 2.0); glEnd(); + // draw lines if we are dragging + if (drag_roll) + { + // when rolling, a line from the centre (where we rotate around) in the + // direction of the mouse pointer should help the user. + double distance = width * width + height * height, + angle = start_angle; + glPushMatrix(); + glTranslatef(centre.x, centre.y, 0.0); + glBegin(GL_LINES); + // starting angle + glVertex2d(0.0, 0.0); + glVertex2f(distance * cos(angle), distance * sin(angle)); + // angle now used + angle += shift_angle; + glVertex2d(0.0, 0.0); + glVertex2f(distance * cos(angle), distance * sin(angle)); + glEnd(); + glPopMatrix(); + } + if (drag_pitch || drag_yaw) + { + // Draw a straight line in the spherical space, from the start point to + // under the mouse. It only appears straight when using a cylinderical + // projection or similar though, so we draw it as many line segments. + glBegin(GL_LINE_STRIP); + for (double t = 0.0; t <= 1.0; t+= 0.005) + { + double x, y, ti = 1.0 - t; + helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage( + x, y, + t * start_coordinates.x + ti *shift_coordinates.x, + t * start_coordinates.y + ti *shift_coordinates.y); + glVertex2d(x, y); + } + glEnd(); + } glPopMatrix(); + glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); } @@ -242,34 +265,37 @@ roll = img->getRoll(); } -void PreviewDragTool::AngleStore::Move(double yaw_shift, double pitch_shift, - double roll_shift, - double yaw_start, double pitch_start, - double roll_start, +void PreviewDragTool::AngleStore::Move(Matrix3 *matrix, double &yaw_out, double &pitch_out, double &roll_out) { - // rotate the start point to the centre - Matrix3 base_rot_matrix, shift_rot_matrix, base_rot_inverse_matrix, - original_matrix, output_matrix; - original_matrix.SetRotationPT(DEG_TO_RAD(yaw), - DEG_TO_RAD(pitch), - DEG_TO_RAD(roll)); - base_rot_matrix.SetRotationPT(-DEG_TO_RAD(yaw_start), - DEG_TO_RAD(pitch_start), - -DEG_TO_RAD(roll_start)); - shift_rot_matrix.SetRotationPT(DEG_TO_RAD(yaw_shift), - -DEG_TO_RAD(pitch_shift), - DEG_TO_RAD(roll_shift)); - /*base_rot_inverse_matrix.SetRotationPT(-DEG_TO_RAD(yaw_start), - DEG_TO_RAD(pitch_start), - DEG_TO_RAD(roll_start));*/ - output_matrix = /*base_rot_inverse_matrix **/ base_rot_matrix * - shift_rot_matrix * original_matrix; - //output_matrix = shift_rot_matrix * original_matrix; - // collect the resultant rotations + Matrix3 start, output_matrix; + // convert the location of this image to a matrix. + start.SetRotationPT(DEG_TO_RAD(yaw), DEG_TO_RAD(pitch), DEG_TO_RAD(roll)); + // move it by the matrix specified. + output_matrix = *matrix * start; + // get the angles from the matrix output_matrix.GetRotationPT(yaw_out, pitch_out, roll_out); yaw_out = RAD_TO_DEG(yaw_out); pitch_out = RAD_TO_DEG(pitch_out); roll_out = RAD_TO_DEG(roll_out); } + +void PreviewDragTool::SetRotationMatrix(double yaw_shift, double pitch_shift, + double roll_shift, + double yaw_start, double pitch_start, + double roll_start) +{ + Matrix3 y1_mat, r_mat, y2_mat, p1_mat, p2_mat; + // rotates the start point to the centre + y1_mat.SetRotationPT(-DEG_TO_RAD(yaw_start), 0.0, 0.0); + p1_mat.SetRotationPT(0.0, DEG_TO_RAD(pitch_start), 0.0); + // rolls the image + r_mat.SetRotationPT(0.0, 0.0, roll_shift); + // rotates the centre to the destination point + p2_mat.SetRotationPT(0.0, -DEG_TO_RAD(pitch_shift), 0.0); + y2_mat.SetRotationPT(DEG_TO_RAD(yaw_shift), 0.0, 0.0); + + rotation_matrix = y2_mat * p2_mat * r_mat *p1_mat * y1_mat; +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -26,16 +26,15 @@ * * Modifiers | Variables changed * none | yaw and pitch - * shift | pitch + * shift | yaw or pitch, depending on biggest difference. * control | roll - * alt or meta | yaw * - * You can also change only pitch by using the secondary mouse button (if there + * You can also change only roll by using the secondary mouse button (if there * is one). * *(Reasoning: control click on mac is equivalent right click on other platforms, - * no modifiers should be close to old behaviour, where modifiers were not used, - * shift and alt chosen arbitrarily but more portable than meta or the like.) + * no modifiers should be close to old behaviour (where no modifiers were used), + * and shift was chosen arbitrarily.) */ #ifndef _PREVIEWDRAGTOOL_H @@ -44,6 +43,7 @@ #include "PreviewTool.h" #include <map> +#include <hugin_math/Matrix3.h> class PreviewDragTool : public PreviewTool { @@ -52,15 +52,13 @@ void Activate(); void MouseMoveEvent(double x, double y); void MouseButtonEvent(wxMouseEvent &e); - void KeypressEvent(int keycode, int modifiers, bool pressed); void AfterDrawImagesEvent(); class AngleStore { public: double yaw, pitch, roll; void Set(HuginBase::SrcPanoImage *img); - void Move(double yaw_shift, double pitch_shift, double roll_shift, - double yaw_start, double pitch_start, double roll_start, + void Move(Matrix3 *matrix, double &yaw_out, double &pitch_out, double &roll_out); }; private: @@ -68,8 +66,13 @@ bool drag_yaw, drag_pitch, drag_roll; double start_angle, shift_angle; hugin_utils::FDiff2D centre, start_coordinates, shift_coordinates; - double base_rot[3]; - bool shift, control, alt; + bool shift, control; + Matrix3 rotation_matrix; + void SetRotationMatrix(double yaw_shift, double pitch_shift, + double roll_shift, + double yaw_start, double pitch_start, + double roll_start); }; #endif + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -156,6 +156,7 @@ // activated. This should be fine if the user clicks the button to activate // the tool. image_set.clear(); + mouse_is_over_button = false; /* TODO if it becomes possible to activate the tool by a keyboard shortcut * or something, call ImagesUnderMouseChangedEvent() to make sure we display * indicators for images currently under the cursor. */ @@ -167,24 +168,47 @@ // to work out which ones are not in the new set, so we can set their // buttons back to the system colour. std::set<unsigned int> new_image_set = helper->GetImageNumbersUnderMouse(); - std::vector<unsigned int> difference(image_set.size()); std::vector<unsigned int>::iterator end; - end = std::set_difference (image_set.begin(), image_set.end(), - new_image_set.begin(), new_image_set.end(), - difference.begin()); - DEBUG_ASSERT(end >= difference.begin() && end <= difference.end()); - std::vector<unsigned int>::iterator iterator; - if (iterator != end) { - for (iterator = difference.begin(); iterator < end; iterator++) + std::vector<unsigned int> difference(image_set.size()); + end = difference.begin(); + end = std::set_difference (image_set.begin(), image_set.end(), + new_image_set.begin(), new_image_set.end(), + difference.begin()); + DEBUG_ASSERT(end >= difference.begin() && end <= difference.end()); + if (difference.begin() != end) { - DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages()); - // reset this button to its default system colour. - preview_frame->SetImageButtonColour(*iterator, 0, 0, 0); - // remove the notification - helper->DoNotNotifyMeBeforeDrawing(*iterator, this); + std::vector<unsigned int>::iterator iterator; + for (iterator = difference.begin(); iterator != end; iterator++) + { + DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages()); + // reset this button to its default system colour. + preview_frame->SetImageButtonColour(*iterator, 0, 0, 0); + // remove the notification + helper->DoNotNotifyMeBeforeDrawing(*iterator, this); + } } } + // now request to be notified when drawing the new ones. + { + std::vector<unsigned int> difference(new_image_set.size()); + end = difference.begin(); + end = std::set_difference (new_image_set.begin(), new_image_set.end(), + image_set.begin(), image_set.end(), + difference.begin()); + DEBUG_ASSERT(end >= difference.begin() && end <= difference.end()); + if (difference.begin() != end) + { + std::vector<unsigned int>::iterator iterator; + for (iterator = difference.begin(); iterator != end; iterator++) + { + DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages()); + // get notification of when this is about to be drawn. + helper->NotifyMeBeforeDrawing(*iterator, this); + } + } + } + // remember the new set. image_set.swap(new_image_set); // Redraw with new indicators. Since the indicators aren't part of the @@ -201,8 +225,10 @@ // background are clearly marked. unsigned int num_images = image_set.size(); // draw the actual images - std::set<unsigned int>::iterator it; - for (it = image_set.begin(); it != image_set.end(); it++) + // the preview draws them in reverse order, so the lowest numbered appears + // on top. We will folow this convention to avoid confusion. + std::set<unsigned int>::reverse_iterator it; + for (it = image_set.rbegin(); it != image_set.rend(); it++) { DEBUG_ASSERT(*it < helper->GetPanoramaPtr()->getNrOfImages()); helper->GetViewStatePtr()->GetTextureManager()-> @@ -214,7 +240,7 @@ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_TEXTURE); unsigned int image_counter = 0; - for (it = image_set.begin(); it != image_set.end(); it++) + for (it = image_set.rbegin(); it != image_set.rend(); it++) { // we want to shift the texture so it lines up with the cropped region. glPushMatrix(); @@ -294,20 +320,33 @@ { DEBUG_ASSERT(image < helper->GetPanoramaPtr()->getNrOfImages()); // Add this image to the set of images drawn. - image_set.insert(image); - // now we want a redraw. - helper->GetViewStatePtr()->ForceRequireRedraw(); - helper->GetViewStatePtr()->Redraw(); + if (!image_set.count(image)) + { + // it is not already in the set. Add it now + image_set.insert(image); + // we want notification of when it is drawn so we can delay drawing. + helper->NotifyMeBeforeDrawing(image, this); + // now we want a redraw. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); + } + mouse_over_image = image; + mouse_is_over_button = true; } void PreviewIdentifyTool::StopShowingImages() { - // set the colour to the image the user just moused off to the default. - preview_frame->SetImageButtonColour(*image_set.begin(), 0, 0, 0); - image_set.clear(); - // now redraw without the indicator. - helper->GetViewStatePtr()->ForceRequireRedraw(); - helper->GetViewStatePtr()->Redraw(); + if (mouse_is_over_button) + { + // set the colour to the image the user just moused off to the default. + preview_frame->SetImageButtonColour(mouse_over_image, 0, 0, 0); + helper->DoNotNotifyMeBeforeDrawing(mouse_over_image, this); + image_set.erase(mouse_over_image); + // now redraw without the indicator. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); + mouse_is_over_button = false; + } } // generate a colour given how many colours we need and an index. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -59,6 +59,9 @@ // the set of image numbers of the images we are displaying. std::set<unsigned int> image_set; GLPreviewFrame *preview_frame; + // the image the use last placed their mouse over the toggle button for: + unsigned int mouse_over_image; + bool mouse_is_over_button; }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -33,6 +33,7 @@ mouse_button_notified_tool = 0; keypress_notified_tool = 0; images_under_mouse_current = false; + mouse_over_pano = true; } PreviewToolHelper::~PreviewToolHelper() @@ -61,6 +62,7 @@ void PreviewToolHelper::MouseMoved(int x, int y) { + mouse_over_pano = true; // work out where the pointer is in the panorama. vigra::Rect2D visible = view_state->GetVisibleArea(); mouse_x = (double) x / view_state->GetScale() + (double) visible.left(); @@ -126,8 +128,13 @@ { (*iterator)->BeforeDrawImagesEvent(); } - // Since we are drawing a new frame, lets assume something has changed. - InvalidateImagesUnderMouse(); + // Since we are drawing a new frame, lets assume something has changed, + // however we want to keep with no images under the mouse if the mouse is + // not on the panorama. + if (mouse_over_pano) + { + InvalidateImagesUnderMouse(); + } } void PreviewToolHelper::AfterDrawImages() @@ -164,6 +171,27 @@ } } +void PreviewToolHelper::MouseLeave() +{ + // if the mouse leaves the preview, there are no images under the mouse + // pointer anymore. + mouse_over_pano = false; + images_under_mouse.clear(); + images_under_mouse_current = true; + if (!images_under_mouse_notified_tools.empty()) + { + // notify tools that the set has changed. + std::set<PreviewTool *>::iterator iterator; + for (iterator = images_under_mouse_notified_tools.begin(); + iterator != images_under_mouse_notified_tools.end(); + iterator++) + { + (*iterator)->ImagesUnderMouseChangedEvent(); + } + } +} + + std::set<unsigned int> PreviewToolHelper::GetImageNumbersUnderMouse() { if (!images_under_mouse_current) @@ -330,7 +358,7 @@ std::vector<PreviewTool *> *vector, unsigned int index) { - if (vector->size() < index) + if (vector->size() < index + 1) { // increase the size of the vector to handle enough elements for index // to exist @@ -347,20 +375,30 @@ void PreviewToolHelper::UpdateImagesUnderMouse() { + // We want to find out which images cover the point underneath the mouse + // pointer. images_under_mouse.clear(); unsigned int num_images = pano->getNrOfImages(); + std::set<unsigned int> displayedImages = pano->getActiveImages(); for (unsigned int image_index = 0; image_index < num_images; image_index++) { - HuginBase::PTools::Transform transform; - transform.createTransform(*view_state->GetSrcImage(image_index), - *view_state->GetOptions()); - double image_x, image_y; - transform.transformImgCoord(image_x, image_y, mouse_x, mouse_y); - if (view_state->GetSrcImage(image_index)->isInside( - vigra::Point2D(int(image_x), int (image_y)))) + // don't try any images that are turned off + if (displayedImages.count(image_index)) { - images_under_mouse.insert(image_index); + // work out if the image covers the point under the mouse. + HuginBase::PTools::Transform transform; + transform.createTransform(*view_state->GetSrcImage(image_index), + *view_state->GetOptions()); + double image_x, image_y; + transform.transformImgCoord(image_x, image_y, mouse_x, mouse_y); + if (view_state->GetSrcImage(image_index)->isInside(vigra::Point2D( + int(image_x), int (image_y)))) + { + // this image is under the mouse, add it to the set. + images_under_mouse.insert(image_index); + } } } images_under_mouse_current = true; } + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -90,6 +90,7 @@ // tools specify otherwise. bool BeforeDrawImageNumber(unsigned int image); void AfterDrawImageNumber(unsigned int image); + void MouseLeave(); // Get information std::set<unsigned int> GetImageNumbersUnderMouse(); @@ -133,7 +134,7 @@ unsigned int index); // is the set of images under the mouse up to date? - bool images_under_mouse_current; + bool images_under_mouse_current, mouse_over_pano; // which images are under the mouse? std::set<unsigned int> images_under_mouse; void UpdateImagesUnderMouse(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -1105,8 +1105,8 @@ // requested stopping node. Anything at a higher depth is after it. if (depth > max_depth) return 0; node_id = GetIndex(no_x, no_y, row_size, depth); + if (depth == max_depth && no_x >= stop_x && no_y >= stop_y) return 0; } - if (depth == max_depth && no_x >= stop_x && no_y >= stop_y) return 0; // if any of the vertices we are want to use are invalid (e.g. behind the // viewer in a rectilinear projection) we don't want to risk using them: if (nodes[node_id].flags & (transform_fail_flag * 15)) return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-05 23:05:40
|
Revision: 3276 http://hugin.svn.sourceforge.net/hugin/?rev=3276&view=rev Author: jlegg Date: 2008-08-05 23:05:37 +0000 (Tue, 05 Aug 2008) Log Message: ----------- Open up the control point editor when the overlap of two images is clicked with the identify tool. Since all tools now respond to mouse clicks they are all mutually exclusive. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-05 18:56:33 UTC (rev 3275) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-05 23:05:37 UTC (rev 3276) @@ -28,6 +28,7 @@ #include "base_wx/platform.h" #include "GLPreviewFrame.h" +#include "MainFrame.h" #include <GL/gl.h> #include <GL/glu.h> @@ -150,6 +151,7 @@ helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); helper->NotifyMe(PreviewToolHelper::IMAGES_UNDER_MOUSE_CHANGE, this); + helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); // clear up // Assume that there are no images under the mouse when the tool is @@ -393,3 +395,16 @@ } } +void PreviewIdentifyTool::MouseButtonEvent(wxMouseEvent & e) +{ + if ( e.GetButton() == wxMOUSE_BTN_LEFT + && image_set.size() == 2) + { + // when there are only two images with indicators shown, show the + // control point editor with those images when left clicked. + MainFrame::Get()->ShowCtrlPointEditor(*(image_set.begin()), + *(++image_set.begin())); + MainFrame::Get()->Raise(); + } +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-05 18:56:33 UTC (rev 3275) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-05 23:05:37 UTC (rev 3276) @@ -49,6 +49,7 @@ // these are called when the user moves the mouse over the image buttons. void ShowImageNumber(unsigned int image); // mouse on void StopShowingImages(); // mouse off + void MouseButtonEvent(wxMouseEvent & e); private: // generate a colour given how many colours we need and an index. void HighlightColour(unsigned int index, unsigned int count, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-06 16:55:47
|
Revision: 3277 http://hugin.svn.sourceforge.net/hugin/?rev=3277&view=rev Author: jlegg Date: 2008-08-06 16:55:43 +0000 (Wed, 06 Aug 2008) Log Message: ----------- Added an experimental difference tool. Set the blend mode to difference and move the mouse over an image to use it. It clashes with the identification tool, trying to use them both at once will disable one, but the gui does not update when this happens. The difference tool doesn't appear to show too many of the preview's approximation errors. However, since colours are clamped in OpenGL it breaks when the panorama is over exposed, which is a counter-intutive since increasing the exposure makes the differences bigger and therefore they should be easier to see. There are also a few bug fixes for PanoramaToolHelper and a fixed memory leak in GLPreviewFrame. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-08-06 16:55:43 UTC (rev 3277) @@ -32,7 +32,8 @@ HFOVDialog.cpp TextureManager.cpp MeshRemapper.cpp VertexCoordRemapper.cpp TexCoordRemapper.cpp ChoosyRemapper.cpp MeshManager.cpp ViewState.cpp OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp -PreviewCropTool.cpp PreviewDragTool.cpp PreviewIdentifyTool.cpp) +PreviewCropTool.cpp PreviewDragTool.cpp PreviewIdentifyTool.cpp +PreviewDifferenceTool.cpp) IF(APPLE) if (MAC_SELF_CONTAINED_BUNDLE) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-06 16:55:43 UTC (rev 3277) @@ -60,6 +60,7 @@ #include "PreviewCropTool.h" #include "PreviewDragTool.h" #include "PreviewIdentifyTool.h" +#include "PreviewDifferenceTool.h" using namespace utils; @@ -414,6 +415,12 @@ } config->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); + + // delete all of the tools + helper->DeactivateTool(crop_tool); delete crop_tool; + helper->DeactivateTool(drag_tool); delete drag_tool; + helper->DeactivateTool(identify_tool); delete identify_tool; + helper->DeactivateTool(difference_tool); delete difference_tool; m_pano.removeObserver(this); DEBUG_TRACE("dtor end"); } @@ -835,17 +842,16 @@ { if (e.GetEventObject() == m_BlendModeChoice) { int sel = e.GetSelection(); - // TODO tell renderer - /*switch (sel) { + switch (sel) { case 0: - m_PreviewPanel->SetBlendMode(PreviewPanel::BLEND_COPY); + helper->DeactivateTool(difference_tool); break; case 1: - m_PreviewPanel->SetBlendMode(PreviewPanel::BLEND_DIFFERENCE); + helper->ActivateTool(difference_tool); break; default: DEBUG_WARN("Unknown blend mode selected"); - }*/ + } } else { // FIXME DEBUG_WARN("wxChoice event from unknown object received"); } @@ -967,6 +973,7 @@ crop_tool = new PreviewCropTool(helper); drag_tool = new PreviewDragTool(helper); identify_tool = new PreviewIdentifyTool(helper, this); + difference_tool = new PreviewDifferenceTool(helper); } void GLPreviewFrame::OnCrop(wxCommandEvent & e) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-06 16:55:43 UTC (rev 3277) @@ -33,6 +33,7 @@ class PreviewCropTool; class PreviewDragTool; class PreviewIdentifyTool; +class PreviewDifferenceTool; // the image toggle buttons need a special event handler to trap mouse enter and // leave events. @@ -154,6 +155,7 @@ PreviewCropTool *crop_tool; PreviewDragTool *drag_tool; PreviewIdentifyTool *identify_tool; + PreviewDifferenceTool *difference_tool; void TurnOffTools(std::set<PreviewTool*> tools); void CleanButtonColours(); }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-08-06 16:55:43 UTC (rev 3277) @@ -137,11 +137,19 @@ // The old preview shows the lowest numbered image on top, so do the same: for (int img = imgs - 1; img != -1; img--) { + // only draw active images if (m_pano->getImage(img).getOptions().active) { - m_tool_helper->BeforeDrawImageNumber(img); - m_tex_man->DrawImage(img, m_mesh_man->GetDisplayList(img)); - m_tool_helper->AfterDrawImageNumber(img); + // the tools can cancel drawing of images. + if (m_tool_helper->BeforeDrawImageNumber(img)) + { + // the texture manager may need to call the display list + // multiple times with blending, so we pass it the display list + // rather than switching to the texture and then calling the + // list ourselves. + m_tex_man->DrawImage(img, m_mesh_man->GetDisplayList(img)); + m_tool_helper->AfterDrawImageNumber(img); + } } } m_tex_man->End(); Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp 2008-08-06 16:55:43 UTC (rev 3277) @@ -0,0 +1,120 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewDifferenceTool.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "PreviewDifferenceTool.h" +#include <GL/glew.h> +#include <GL/gl.h> + +PreviewDifferenceTool::PreviewDifferenceTool(PreviewToolHelper *helper) + : PreviewTool(helper) +{ + // rather boring constructor +} + +void PreviewDifferenceTool::Activate() +{ + over_image = false; + helper->NotifyMe(PreviewToolHelper::IMAGES_UNDER_MOUSE_CHANGE, this); +} + +void PreviewDifferenceTool::ImagesUnderMouseChangedEvent() +{ + std::set<unsigned int> image_set = helper->GetImageNumbersUnderMouse(); + if (!image_set.empty()) + { + // stop showing the previous one if there was one, if there wasn't, we + // need to be able to draw over the preview. + if (over_image) + { + helper->DoNotNotifyMeBeforeDrawing(image_number, this); + } else { + helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); + } + // The lowest image number is drawn first, since the set is sorted. + // Get notifications so we can draw it: + image_number = *(image_set.begin()); + helper->NotifyMeBeforeDrawing(image_number, this); + // Redraw the panorama with this image negated from the others. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); + over_image = true; + } else { + if (over_image) + { + // We were showing a difference, now there are no images under the + // mouse pointer: + // Drop notifications, we don't need to do anything extra. + over_image = false; + helper->DoNotNotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); + helper->DoNotNotifyMeBeforeDrawing(image_number, this); + // redraw the panorama without the negated image. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); + } + } +} + +void PreviewDifferenceTool::AfterDrawImagesEvent() +{ + // Get the display list used to generate the image + unsigned int display_list, texture_number; + display_list = helper->GetViewStatePtr()->GetMeshDisplayList(image_number); + TextureManager *tex_m = helper->GetViewStatePtr()->GetTextureManager(); + texture_number = tex_m->GetTextureName(image_number); + glBindTexture(GL_TEXTURE_2D, texture_number); + // we will use a subtractive blend + glBlendEquation(GL_FUNC_SUBTRACT); + glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_BLEND); + if (tex_m->GetPhotometricCorrect()) + { + // The texture has full photometric correction, we can subtract it once + // and be done. + glCallList(display_list); + } else { + // otherwise we have to fake some of the photometric correction to get + // good white balance and exposure. + HuginBase::SrcPanoImage *img; + img = helper->GetViewStatePtr()->GetSrcImage(image_number); + float viewer_exposure = 1.0 / pow(2.0, + helper->GetPanoramaPtr()->getOptions().outputExposureValue); + float es = viewer_exposure / img->getExposure(); + float scale[3] = {es / img->getWhiteBalanceRed(), + es, + es / img->getWhiteBalanceBlue()}; + // now we draw repeatedly until the image has been exposed properly. + while (scale[0] > 0.0 && scale[1] > 0.0 && scale[2] > 0.0) + { + glColor3fv(scale); + glCallList(display_list); + scale[0] -= 1.0; scale[1] -= 1.0; scale[2] -= 1.0; + } + glColor3f(1.0, 1.0, 1.0); + } + glBlendEquation(GL_FUNC_ADD); + glDisable(GL_BLEND); +} + +bool PreviewDifferenceTool::BeforeDrawImageEvent(unsigned int image) +{ + return false; +} + Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.h (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.h 2008-08-06 16:55:43 UTC (rev 3277) @@ -0,0 +1,52 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewDifferenceTool.h + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* The PreviewDifferenceTool finds the topmost image underneath the mouse + * pontier, which it cancels the normal draw for, and then subtracts it from the + * rest of the images. + * It is meant to be the fast preview's equivalent of the accurate preview's + * difference mode. + * WARNING: Since the fast preview is approximate, this will show errors that + * don't really exist. + */ + +#ifndef _PREVIEWDIFFERENCETOOL_H +#define _PREVIEWDIFFERENCETOOL_H + +#include "PreviewTool.h" + +class PreviewDifferenceTool : public PreviewTool +{ +public: + PreviewDifferenceTool(PreviewToolHelper *helper); + // ~PreviewIdentifyTool(); + void Activate(); + void ImagesUnderMouseChangedEvent(); + void AfterDrawImagesEvent(); + bool BeforeDrawImageEvent(unsigned int image); + // these are called when the user moves the mouse over the image buttons. +private: + unsigned int image_number; + bool over_image; +}; + +#endif + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-06 16:55:43 UTC (rev 3277) @@ -310,7 +310,7 @@ glColor3ub(255, 255, 255); } -bool PreviewIdentifyTool::BeforeDrawImageNumber(unsigned int image) +bool PreviewIdentifyTool::BeforeDrawImageEvent(unsigned int image) { // Delay drawing of images, so we can show them on top of the others. DEBUG_ASSERT(image < helper->GetPanoramaPtr()->getNrOfImages()); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-06 16:55:43 UTC (rev 3277) @@ -45,7 +45,7 @@ void Activate(); void ImagesUnderMouseChangedEvent(); void AfterDrawImagesEvent(); - bool BeforeDrawImageNumber(unsigned int image); + bool BeforeDrawImageEvent(unsigned int image); // these are called when the user moves the mouse over the image buttons. void ShowImageNumber(unsigned int image); // mouse on void StopShowingImages(); // mouse off Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-06 16:55:43 UTC (rev 3277) @@ -58,6 +58,7 @@ RemoveTool(tool, &draw_over_notified_tools); RemoveTool(tool, &image_draw_begin_tools); RemoveTool(tool, &image_draw_end_tools); + RemoveTool(tool, &images_under_mouse_notified_tools); } void PreviewToolHelper::MouseMoved(int x, int y) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-06 16:55:43 UTC (rev 3277) @@ -119,6 +119,16 @@ } } +unsigned int TextureManager::GetTextureName(unsigned int image_number) +{ + // bind the texture that represents the given image number. + std::map<TextureKey, TextureInfo>::iterator it; + HuginBase::SrcPanoImage *img_p = view_state->GetSrcImage(image_number); + TextureKey key(img_p, &photometric_correct); + it = textures.find(key); + return it->second.GetNumber(); +} + void TextureManager::Begin() { if (!photometric_correct) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-08-05 23:05:37 UTC (rev 3276) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-08-06 16:55:43 UTC (rev 3277) @@ -62,6 +62,8 @@ void SetPhotometricCorrect(bool state); // return true if we are doing photometric correction. bool GetPhotometricCorrect() {return photometric_correct;} + // get the OpneGL texture name for a given image + unsigned int GetTextureName(unsigned int image_number); protected: PT::Panorama * m_pano; ViewState *view_state; @@ -93,8 +95,9 @@ HuginBase::SrcPanoImage *state); void SetMaxLevel(int level); void Bind(); + unsigned int GetNumber() {return num;}; private: - unsigned int num; // num is the openGL texture name + unsigned int num; // the openGL texture name // this binds a new texture in openGL and sets the various parameters // we need for it. void CreateTexture(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-12 17:03:43
|
Revision: 3311 http://hugin.svn.sourceforge.net/hugin/?rev=3311&view=rev Author: jlegg Date: 2008-08-12 17:03:33 +0000 (Tue, 12 Aug 2008) Log Message: ----------- A few bug fixes and usability improvements. You can turn on or off the constraints in the drag tool by pressing and releasing shift with the mouse button held. The difference tool and identify tool are now properly mutually exclusive. The difference tool brightens the result for visibility, and subtracts the other way around (pano - image). The status bar message is changed by the tools. The texture manager previously copied images unnecessarily, that is fixed. The scaling is picked a little better, not scaling up very small images so much, and using closer to the budget of texture space. It also supports masks now, although these aren't displayed perfectly when the image is brightened due to the limitations of some OpenGL implementations. (In semi-transparent places, the previously drawn images are brightened as well.) It won't crash or do any undefined behaviour with tiny images either. (Still not using SmallImageCache though.) Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-08-12 17:03:33 UTC (rev 3311) @@ -33,7 +33,7 @@ TexCoordRemapper.cpp ChoosyRemapper.cpp MeshManager.cpp ViewState.cpp OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp PreviewCropTool.cpp PreviewDragTool.cpp PreviewIdentifyTool.cpp -PreviewDifferenceTool.cpp) +PreviewDifferenceTool.cpp PreviewPanoMaskTool.cpp) IF(APPLE) if (MAC_SELF_CONTAINED_BUNDLE) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -45,7 +45,8 @@ // something messed up... temporary fix :-( #include "hugin_utils/utils.h" #define DEBUG_HEADER "" -#include <vigra_ext/ImageTransforms.h> +/*#include <vigra_ext/ImageTransforms.h> +*/ extern "C" { #ifdef HasPANO13 @@ -61,6 +62,7 @@ #include "PreviewDragTool.h" #include "PreviewIdentifyTool.h" #include "PreviewDifferenceTool.h" +#include "PreviewPanoMaskTool.h" using namespace utils; @@ -248,7 +250,7 @@ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); - // TODO implement difference blend mode and hdr display in OpenGL. + ////////////////////////////////////////////////////// // Blend mode blendModeSizer->Add(new wxStaticText(this, -1, _("Blend mode:")), @@ -259,7 +261,7 @@ m_choices[0] = _("normal"); m_choices[1] = _("difference"); - int oldMode = wxConfigBase::Get()->Read(wxT("/PreviewFrame/blendMode"), 0l); + int oldMode = wxConfigBase::Get()->Read(wxT("/GLPreviewFrame/blendMode"), 0l); if (oldMode > 1) oldMode = 0; m_BlendModeChoice = new wxChoice(this, ID_BLEND_CHOICE, wxDefaultPosition, wxDefaultSize, @@ -272,6 +274,7 @@ wxALL | wxALIGN_CENTER_VERTICAL, 5); + // TODO implement hdr display in OpenGL, if possible? ////////////////////////////////////////////////////// // LDR, HDR blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")), @@ -366,7 +369,6 @@ CreateStatusBar(3); int widths[3] = {-3, 150, 150}; SetStatusWidths(3, widths); - // SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0); SetStatusText(wxT(""),1); SetStatusText(wxT(""),2); @@ -397,7 +399,7 @@ if (config->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0) { Show(); } - SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0); + crop_tool = 0; } GLPreviewFrame::~GLPreviewFrame() @@ -416,11 +418,16 @@ config->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); - // delete all of the tools - helper->DeactivateTool(crop_tool); delete crop_tool; - helper->DeactivateTool(drag_tool); delete drag_tool; - helper->DeactivateTool(identify_tool); delete identify_tool; - helper->DeactivateTool(difference_tool); delete difference_tool; + // delete all of the tools. When the preview is never used we never get an + // OpenGL context and therefore don't create the tools. + if (crop_tool) + { + helper->DeactivateTool(crop_tool); delete crop_tool; + helper->DeactivateTool(drag_tool); delete drag_tool; + helper->DeactivateTool(identify_tool); delete identify_tool; + helper->DeactivateTool(difference_tool); delete difference_tool; + helper->DeactivateTool(pano_mask_tool); delete pano_mask_tool; + } m_pano.removeObserver(this); DEBUG_TRACE("dtor end"); } @@ -499,8 +506,7 @@ if (relayout) { m_topsizer->Layout(); } -#endif - SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0); +#endif SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2); m_HFOVSlider->SetValue(roundi(opts.getHFOV())); m_VFOVSlider->SetValue(roundi(opts.getVFOV())); @@ -847,7 +853,10 @@ helper->DeactivateTool(difference_tool); break; case 1: + helper->DeactivateTool(identify_tool); + m_ToolBar->ToggleTool(identify_tool_id, false); helper->ActivateTool(difference_tool); + CleanButtonColours(); break; default: DEBUG_WARN("Unknown blend mode selected"); @@ -959,6 +968,12 @@ #endif } +void GLPreviewFrame::SetStatusMessage(wxString message) +{ + SetStatusText(message, 0); +} + + void GLPreviewFrame::OnPhotometric(wxCommandEvent & e) { m_GLViewer->SetPhotometricCorrect(e.IsChecked()); @@ -974,11 +989,16 @@ drag_tool = new PreviewDragTool(helper); identify_tool = new PreviewIdentifyTool(helper, this); difference_tool = new PreviewDifferenceTool(helper); + pano_mask_tool = new PreviewPanoMaskTool(helper); + + // activate tools that are always active. + helper->ActivateTool(pano_mask_tool); } void GLPreviewFrame::OnCrop(wxCommandEvent & e) { // turn on or off the crop tool when its button is pressed. + SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool. if (e.IsChecked()) { // ActivateTool returns pointers to the tools that were switched off to @@ -993,6 +1013,7 @@ void GLPreviewFrame::OnDrag(wxCommandEvent & e) { + SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool. if (e.IsChecked()) { TurnOffTools(helper->ActivateTool(drag_tool)); @@ -1005,8 +1026,11 @@ void GLPreviewFrame::OnIdentify(wxCommandEvent & e) { + SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool. if (e.IsChecked()) { + m_BlendModeChoice->SetSelection(0); + helper->DeactivateTool(difference_tool); TurnOffTools(helper->ActivateTool(identify_tool)); } else { helper->DeactivateTool(identify_tool); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -26,7 +26,17 @@ class wxToolBar; class wxToggleButton; class wxCheckBox; +class wxTextCtrl; +class wxBitmapButton; +class wxSpinButton; +class wxScrolledWindow; +class wxBoxSizer; +class wxStaticBoxSizer; +class wxStaticText; +class wxSlider; class GLViewer; +class wxSpinEvent; +class wxChoice; class PreviewToolHelper; class PreviewTool; @@ -34,10 +44,14 @@ class PreviewDragTool; class PreviewIdentifyTool; class PreviewDifferenceTool; +class PreviewPanoMaskTool; +#include "common/utils.h" +#include <wx/string.h> +#include <wx/frame.h> + // the image toggle buttons need a special event handler to trap mouse enter and // leave events. - class ImageToogleButtonEventHandler : public wxEvtHandler { public: @@ -86,6 +100,7 @@ void MakeTools(PreviewToolHelper * helper); void SetImageButtonColour(unsigned int image_nr, unsigned char red, unsigned char green, unsigned char blue); + void SetStatusMessage(wxString message); protected: void OnClose(wxCloseEvent& e); @@ -156,6 +171,7 @@ PreviewDragTool *drag_tool; PreviewIdentifyTool *identify_tool; PreviewDifferenceTool *difference_tool; + PreviewPanoMaskTool *pano_mask_tool; void TurnOffTools(std::set<PreviewTool*> tools); void CleanButtonColours(); }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -31,7 +31,7 @@ // TODO needed? //#include <vector> -/* something messed up... temporary fix :-(*/ +/* something messed up... temporary fix :-( */ #include "hugin_utils/utils.h" #define DEBUG_HEADER "" #include <base_wx/ImageCache.h> Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -83,11 +83,8 @@ // set the context std::cout << "Setting rendering context:\n"; Show(); - //SetCurrent(*m_glContext); m_glContext->SetCurrent(*this); std::cout << "OK\n"; - // a rendering context isn't much use without a renderer and texture manager - // that use it... so create those if necessary as well. if (!started_creation) { // It appears we are setting up for the first time. @@ -110,7 +107,7 @@ // we need something to store the state of the view and control updates m_view_state = new ViewState(m_pano, RefreshWrapper, this); // Start the tools going: - m_tool_helper = new PreviewToolHelper(m_pano, m_view_state); + m_tool_helper = new PreviewToolHelper(m_pano, m_view_state, frame); frame->MakeTools(m_tool_helper); // now make a renderer m_renderer = new GLRenderer(m_pano, m_view_state->GetTextureManager(), @@ -182,7 +179,7 @@ void GLViewer::MouseMotion(wxMouseEvent& e) { m_tool_helper->MouseMoved((int) e.m_x - offset.x, - (int) e.m_y - offset.y); + (int) e.m_y - offset.y, e); } void GLViewer::MouseLeave(wxMouseEvent & e) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -66,29 +66,13 @@ // ...or at least they can be detected from the sides (disk-likes) // I've offset the noth pole slightly as the detection rate was // not 100% - transform.transformImgCoord(x, y, 3.0, 90.0); - north_pole_x = x; + transform.transformImgCoord(x, y, 0.5, 90.0); + north_pole_x = x; north_pole_y = y; - transform.transformImgCoord(x, y, 360.0, 90.0); + transform.transformImgCoord(x, y, 359.5, 90.0); south_pole_x = x; south_pole_y = y; break; - case HuginBase::PanoramaOptions::RECTILINEAR: - // the pole and boundary like problems come at half the angle for - // rectilinear projections. - transform.transformImgCoord(x, y, 93.0, 90.0); - north_pole_x = x; - north_pole_y = y; - radius = -x + output->getSize()->x / 2.0; - transform.transformImgCoord(x, y, 270.0, 90.0); - south_pole_x = x; - south_pole_y = y; - - transform.transformImgCoord(x, y, 150.0, 90.0); - lower_x = x; - transform.transformImgCoord(x, y, 230.0, 90.0); - upper_x = x; - break; default: break; } @@ -100,7 +84,7 @@ const double OutputProjectionInfo::GetUpperX(const double y) const { double temp, pitch, result; - reverse_transform.transformImgCoord(temp, pitch, 0, y); + reverse_transform.transformImgCoord(temp, pitch, 180, y); transform.transformImgCoord(result, temp, 240.0, pitch); return result; } @@ -108,7 +92,7 @@ const double OutputProjectionInfo::GetLowerX(const double y) const { double temp, pitch, result; - reverse_transform.transformImgCoord(temp, pitch, 0, y); + reverse_transform.transformImgCoord(temp, pitch, 180, y); transform.transformImgCoord(result, temp, 120.0, pitch); return result; } @@ -117,7 +101,7 @@ const double OutputProjectionInfo::GetXAdd360(const double y) const { double temp, pitch, result; - reverse_transform.transformImgCoord(temp, pitch, 0, y); + reverse_transform.transformImgCoord(temp, pitch, 180, y); transform.transformImgCoord(result, temp, 0.0, pitch); return result * -2.0 + proj->getSize()->x; } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -45,7 +45,8 @@ moving_left = false; moving_right = false; moving_top = false; - moving_bottom = false; + moving_bottom = false; + helper->SetStatusMessage(_("Drag the inside of the cropping rectangle to adjust the crop.")); } void PreviewCropTool::AfterDrawImagesEvent() @@ -103,7 +104,7 @@ glDisable(GL_BLEND); } -void PreviewCropTool::MouseMoveEvent(double x, double y) +void PreviewCropTool::MouseMoveEvent(double x, double y, wxMouseEvent & e) { if (mouse_down) { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -34,7 +34,7 @@ PreviewCropTool(PreviewToolHelper *helper); void Activate(); void AfterDrawImagesEvent(); - void MouseMoveEvent(double x, double y); + void MouseMoveEvent(double x, double y, wxMouseEvent & e); void MouseButtonEvent(wxMouseEvent &e); private: bool moving_left, moving_right, moving_top, moving_bottom, mouse_down; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -23,6 +23,11 @@ #include <GL/glew.h> #include <GL/gl.h> +// This is the number of times to double the result of the difference. It should +// be between 0 and 7. Note that with values > 0 no extra colours are used +// (infact less are due to clipping), but the difference becomes easier to see. +#define DIFFERENCE_DOUBLE 2 + PreviewDifferenceTool::PreviewDifferenceTool(PreviewToolHelper *helper) : PreviewTool(helper) { @@ -81,7 +86,7 @@ texture_number = tex_m->GetTextureName(image_number); glBindTexture(GL_TEXTURE_2D, texture_number); // we will use a subtractive blend - glBlendEquation(GL_FUNC_SUBTRACT); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); if (tex_m->GetPhotometricCorrect()) @@ -110,6 +115,14 @@ glColor3f(1.0, 1.0, 1.0); } glBlendEquation(GL_FUNC_ADD); + // To make the difference stand out more, multiply it a few times: + glDisable(GL_TEXTURE_2D); + glBlendFunc(GL_DST_COLOR, GL_ONE); + for (unsigned short int count = 0; count < DIFFERENCE_DOUBLE; count++) + { + glCallList(display_list); + } + glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -43,9 +43,11 @@ helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); + // a handy message for the user: + helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or ctrl-drag.")); } -void PreviewDragTool::MouseMoveEvent(double x, double y) +void PreviewDragTool::MouseMoveEvent(double x, double y, wxMouseEvent & e) { if (drag_yaw || drag_pitch || drag_roll) { @@ -58,16 +60,21 @@ pitch, x, y); shift_coordinates.x = yaw; shift_coordinates.y = pitch; + shift = e.m_shiftDown; if (shift) { if (abs(shift_coordinates.x - start_coordinates.x) < abs(shift_coordinates.y - start_coordinates.y)) { shift_coordinates.x = start_coordinates.x; + helper->SetStatusMessage(_("Currently constrained to moving only pitch. Make a larger movement in the opposite direction to constrain to yaw.")); + } else { shift_coordinates.y = start_coordinates.y; + helper->SetStatusMessage(_("Currently constrained to moving only yaw. Make a larger movement in the opposite direction to constrain to pitch.")); } } + } if (drag_roll) { @@ -125,12 +132,15 @@ // set centre and angle helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage( centre.x, centre.y, 0.0, 0.0); + centre.x += 0.5; + centre.y += 0.5; hugin_utils::FDiff2D angular = helper->GetMousePosition() - centre; start_angle = atan2(angular.y, angular.x); shift_angle = 0.0; // we'll always rotate around the centre of the panorama. start_coordinates.x = 0.0; start_coordinates.y = 0.0; shift_coordinates.x = 0.0; shift_coordinates.y = 0.0; + helper->SetStatusMessage(_("Rotate around the centre to roll.")); } if (drag_yaw || drag_pitch) { @@ -149,6 +159,12 @@ pitch, mouse_pos.x, mouse_pos.y); start_coordinates.x = yaw; start_coordinates.y = pitch; shift_coordinates.x = yaw; shift_coordinates.y = pitch; + // provide a helpfull message to the user via the staus bar. + if (shift) { + helper->SetStatusMessage(_("Constrained drag: make a movement and it will be snapped to the yaw or pitch.")); + } else { + helper->SetStatusMessage(_("Drag to move.")); + } } if (drag_roll || drag_yaw || drag_pitch) { @@ -193,6 +209,8 @@ // stop dragging image_angles.clear(); drag_yaw = false; drag_pitch = false; drag_roll = false; + + helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or ctrl-drag.")); } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -50,7 +50,7 @@ public: PreviewDragTool(PreviewToolHelper *helper); void Activate(); - void MouseMoveEvent(double x, double y); + void MouseMoveEvent(double x, double y, wxMouseEvent & e); void MouseButtonEvent(wxMouseEvent &e); void AfterDrawImagesEvent(); class AngleStore Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -162,6 +162,8 @@ /* TODO if it becomes possible to activate the tool by a keyboard shortcut * or something, call ImagesUnderMouseChangedEvent() to make sure we display * indicators for images currently under the cursor. */ + + helper->SetStatusMessage(_("Move the mouse over the images or image buttons to identify them.")); } void PreviewIdentifyTool::ImagesUnderMouseChangedEvent() @@ -218,6 +220,14 @@ // viewstate that a redraw is required. helper->GetViewStatePtr()->ForceRequireRedraw(); helper->GetViewStatePtr()->Redraw(); + + // if there is exactly two images, tell the user they can click to edit CPs. + if (image_set.size() == 2) + { + helper->SetStatusMessage(_("Click to create or edit control points here.")); + } else { + helper->SetStatusMessage(_("Move the mouse over the images or image buttons to identify them.")); + } } void PreviewIdentifyTool::AfterDrawImagesEvent() Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -48,7 +48,7 @@ // These are called when events happen, providing we requested notification. // The coordinates are in the space of the panorama output at full size. - virtual void MouseMoveEvent(double x, double y) {} + virtual void MouseMoveEvent(double x, double y, wxMouseEvent & e) {} virtual void MouseButtonEvent(wxMouseEvent &e) {} virtual void ImagesUnderMouseChangedEvent() {} virtual void KeypressEvent(int keycode, int modifiers, bool pressed) {} Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -23,13 +23,15 @@ #include "PreviewToolHelper.h" #include "PreviewTool.h" +#include "GLPreviewFrame.h" - PreviewToolHelper::PreviewToolHelper(PT::Panorama *pano_in, - ViewState *view_state_in) + ViewState *view_state_in, + GLPreviewFrame *frame_in) { pano = pano_in; view_state = view_state_in; + frame = frame_in; mouse_button_notified_tool = 0; keypress_notified_tool = 0; images_under_mouse_current = false; @@ -61,7 +63,7 @@ RemoveTool(tool, &images_under_mouse_notified_tools); } -void PreviewToolHelper::MouseMoved(int x, int y) +void PreviewToolHelper::MouseMoved(int x, int y, wxMouseEvent & e) { mouse_over_pano = true; // work out where the pointer is in the panorama. @@ -73,7 +75,7 @@ for (iterator = mouse_move_notified_tools.begin(); iterator != mouse_move_notified_tools.end(); iterator++) { - (*iterator)->MouseMoveEvent(mouse_x, mouse_y); + (*iterator)->MouseMoveEvent(mouse_x, mouse_y, e); } // If the mouse has moved, then we don't know what is underneath it anoymore InvalidateImagesUnderMouse(); @@ -293,6 +295,13 @@ RemoveTool(tool, &image_draw_end_tools, image_nr); } +void PreviewToolHelper::SetStatusMessage(wxString message) +{ + // get the GLPreviewFrame to set its status bar's text. + frame->SetStatusMessage(message); +} + + // These functions remove tools from various things that keep pointers to them // so that they can be notified. They are called when we don't want to notify // them anymore. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -49,6 +49,7 @@ #include <wx/defs.h> #include <wx/event.h> +#include <wx/string.h> #include <set> #include <vector> @@ -58,6 +59,7 @@ #include "PT/Panorama.h" class PreviewTool; +class GLPreviewFrame; class PreviewToolHelper { @@ -69,7 +71,8 @@ IMAGES_UNDER_MOUSE_CHANGE }; PreviewToolHelper(PT::Panorama *pano, - ViewState *view_state); + ViewState *view_state, + GLPreviewFrame * frame); ~PreviewToolHelper(); // working with tools // Activate a tool, the tool will then request notifications it needs. @@ -79,7 +82,8 @@ void DeactivateTool(PreviewTool *tool); // Events - void MouseMoved(int x, int y); + // the x and y coordinates are in pixels from the top left of the panorama. + void MouseMoved(int x, int y, wxMouseEvent & e); // pressed is true if the button is pushed down, false if let go void MouseButtonEvent(wxMouseEvent &e); // keycode is the wxWidgets keycode. @@ -104,11 +108,16 @@ void NotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); void DoNotNotifyMe(Event event, PreviewTool *tool); void DoNotNotifyMeBeforeDrawing(unsigned int image_nr, PreviewTool *tool); - void DoNotNotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); + void DoNotNotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); + + // status message to be something relevant for a tool. + void SetStatusMessage(wxString message); private: std::set<PreviewTool *> tools_deactivated; PT::Panorama *pano; ViewState *view_state; + GLPreviewFrame *frame; + double mouse_x, mouse_y; // What tools are notified of what events. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -69,6 +69,12 @@ TextureKey key(img_p, &photometric_correct); it = textures.find(key); it->second.Bind(); + if (it->second.GetUseAlpha()) + { + // use an alpha blend if + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } if (!photometric_correct) { // When using real time photometric correction, we multiply the colour @@ -82,15 +88,21 @@ 1.0}; glColor3fv(scale); glCallList(display_list); - // since the intensity was clamped to 0.0 - 1.0, we might overdraw a + // Since the intensity was clamped to 0.0 - 1.0, we might overdraw a // few times to make it brighter. + // FIXME If the image has areas masked out, these will also be + // brightened. It might be better to do using the texture, but this + // way we can only add the texture to the frame buffer, (we can't double + // the intensity multiple times) and there is a cost in processing the + // texture. It also won't work properly on partially transparent places. if (scale[0] > 1.0 || scale[1] > 1.0 || scale[2] > 1.0) { glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_ONE); glColor4f(1.0, 1.0, 1.0, 1.0); - // double the brightness for colour components until it is almost right + // double the brightness for colour components until it is almost + // right bool r, g, b; while ( (r = (scale[0] > 2.0)) || (g = (scale[1] > 2.0)) @@ -112,10 +124,15 @@ } glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); + glColor3f(1.0, 1.0, 1.0); } } else { // we've already corrected all the photometrics, just draw once normally glCallList(display_list); + if (it->second.GetUseAlpha()) + { + glDisable(GL_BLEND); + } } } @@ -141,12 +158,6 @@ void TextureManager::End() { - if (!photometric_correct) - { - // set the colour back to normal after using it for photometric - // correction. We expect it to be in this state for drawing other things - glColor3f(1.0, 1.0, 1.0); - } } void TextureManager::CheckUpdate() @@ -309,10 +320,16 @@ // we would like a texture this size: ideal_tex_width = sqrt(ideal_texels / aspect), ideal_tex_height = aspect * ideal_tex_width; + // shrink if bigger than the original, avoids scaling up excessively. + if (ideal_tex_width > img_p->getSize().width()) + ideal_tex_width = img_p->getSize().width(); + if (ideal_tex_height > img_p->getSize().height()) + ideal_tex_height = img_p->getSize().height(); // we will need to round up/down to a power of two + // round up first, then shrink if over budget. // store the power that 2 is raised to, not the actual size - unsigned int tex_width_p = int(log2(ideal_tex_width)), - tex_height_p = int(log2(ideal_tex_height)); + unsigned int tex_width_p = int(log2(ideal_tex_width)) + 1, + tex_height_p = int(log2(ideal_tex_height)) + 1; // check this is hardware supported. { unsigned int biggest = GetMaxTextureSizePower(); @@ -380,7 +397,7 @@ * photometric transformation. * Be warned that when turning off photometric correction, two images * with the same filename will suddenly have the same key, which will - * break the textures map. */ + * break the textures map, hence clearing now */ textures.clear(); } } @@ -395,6 +412,8 @@ // Note: since we use mipmaps, the amount of actual maximum of pixels stored // will be 4/3 of this value. It should use a maximum of 8MB of video memory // for 8 bits per channel rgb images, 12MB if we include a mask. + // Video memory is also used for two copies of the screen and any auxilary + // buffers, and the meshes, so we should do fine with ~24MB of video memory. } unsigned int TextureManager::GetMaxTextureSizePower() @@ -424,19 +443,19 @@ // TODO can this be more efficient? unsigned int num_images = m_pano->getNrOfImages(); bool retry = true; + std::map<TextureKey, TextureInfo>::iterator tex; while (retry) { retry = false; - std::map<TextureKey, TextureInfo>::iterator tex; for (tex = textures.begin(); tex != textures.end(); tex++) { bool found = false; + // try and find an image with this key for (unsigned int img = 0; img < num_images; img++) { - if (TextureKey(view_state->GetSrcImage(img), - &photometric_correct) - == tex->first) + TextureKey ik(view_state->GetSrcImage(img), &photometric_correct); + if (ik == tex->first) { found = true; break; @@ -549,38 +568,55 @@ // add more detail textures. We need to get the biggest one first. // find the original image to scale down. // TODO cache full texture to disk after scaling? - // TODO masks? // TODO use small image if don't need bigger? // It is also possible to use HDR textures, but I can't see the point using // them as the only difference on an LDR display would be spending extra // time reading the texture and converting the numbers. (float and uint16) std::cout << "Loading image\n"; ImageCache::EntryPtr entry = ImageCache::getInstance().getImage( - src_img->getFilename()); + src_img->getFilename()); std::cout << "Converting to 8 bits\n"; - vigra::BRGBImage img = *(entry->get8BitImage()); + boost::shared_ptr<vigra::BRGBImage> img = (entry->get8BitImage()); // first make the biggest mip level. int wo = 1 << (width_p - min), ho = 1 << (height_p - min); if (wo < 1) wo = 1; if (ho < 1) ho = 1; // use Vigra to resize image std::cout << "Scaling image\n"; vigra::BRGBImage out_img(wo, ho); + // also read in the mask. OpenGL requires that the mask is in the same array + // as the colour data, but the ImageCache doesn't work in this way. + vigra::UInt8Image out_alpha(wo, ho); + has_mask = entry->mask->width() != 0; if (wo < 2 || ho < 2) { // too small for vigra to scale - // we still need to define some mipmap levels though. - for (int mip = min; mip < max; mip++) + // we still need to define some mipmap levels though, so use only (0, 0) + for (int h = 0; h < ho; h++) { - // TODO - // glTexImage2D(GL_TEXURE_2D, GL_RGB8, + for (int w = 0; w < wo; w++) + { + out_img[h][w] = (*img)[0][0]; + if (has_mask) out_alpha[h][w] = (*entry->mask)[0][0]; + } } } else { // I think this takes to long, although it should be prettier. - /*vigra::resizeImageLinearInterpolation(srcImageRange(img), - destImageRange(out_img)); /**/ - // much faster - vigra::resizeImageNoInterpolation(srcImageRange(img), - destImageRange(out_img)); /**/ + /*vigra::resizeImageLinearInterpolation(srcImageRange(*img), + destImageRange(out_img)); + if (has_mask) + { + vigra::resizeImageLinearInterpolation(srcImageRange(*(entry->mask)), + destImageRange(out_alpha)); + }/**/ + + // much faster. It shouldn't be so bad after it + vigra::resizeImageNoInterpolation(srcImageRange(*img), + destImageRange(out_img)); + if (has_mask) + { + vigra::resizeImageNoInterpolation(srcImageRange(*(entry->mask)), + destImageRange(out_alpha)); + }/**/ // now perform photometric correction if (photometric_correct) { @@ -619,32 +655,50 @@ hugin_utils::FDiff2D(sx, sy)); } } - } - // TODO read in the masks. - // make all of the smaller ones until we are done. - // this will use a box filter. - // dependent on OpenGL 1.3. Might need an alternative for 1.2. - // TODO use texture compresion? - std::cout << "Defining mipmap levels " << min << " to " << max - << " of texture " << num << ", starting with a size of " - << wo << " by " << ho << ".\n"; - GLint error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, wo, ho, - //GLint error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, width, height, - GL_RGB, GL_UNSIGNED_BYTE, min, min, max, - (unsigned char *) out_img.data()); - if (error) + } + + // make all of the smaller ones until we are done. + // this will use a box filter. + // dependent on OpenGL 1.3. Might need an alternative for 1.2. + // TODO use texture compresion? + std::cout << "Defining mipmap levels " << min << " to " << max + << " of texture " << num << ", starting with a size of " + << wo << " by " << ho << ".\n"; + GLint error; + if (has_mask) + { + // combine the alpha bitmap with the red green and blue one. + unsigned char image[ho][wo][4]; + for (int h = 0; h < ho; h++) { - std::cout << "GLU Error when building mipmap levels: " - << gluErrorString(error) << ".\n"; + for (int w = 0; w < wo; w++) + { + image[h][w][0] = out_img[h][w].red(); + image[h][w][1] = out_img[h][w].green(); + image[h][w][2] = out_img[h][w].blue(); + image[h][w][3] = out_alpha[h][w]; + } } - error = glGetError(); - if (error != GL_NO_ERROR) - { - std::cout << "GL Error when bulding mipmap levels: " - << gluErrorString(error) << ".\n."; - } + error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGBA8, wo, ho, + GL_RGBA, GL_UNSIGNED_BYTE, min, min, max, image); + } else { + // we don't need to rearange the data in memory if there is no mask. + error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, wo, ho, + GL_RGB, GL_UNSIGNED_BYTE, min, min, max, + (unsigned char *) out_img.data()); } + if (error) + { + std::cout << "GLU Error when building mipmap levels: " + << gluErrorString(error) << ".\n"; + } + error = glGetError(); + if (error != GL_NO_ERROR) + { + std::cout << "GL Error when bulding mipmap levels: " + << gluErrorString(error) << ".\n."; + } SetParameters(); std::cout << "Finsihed loading texture.\n"; } @@ -654,9 +708,8 @@ // we want to tell openGL the highest defined mip level of our texture. Bind(); // FIXME the ati graphics driver on Ubuntu is known to crash due to this - // practice. ati users should disable direct renderering for now. - // it will work if there is only one image, or if all images fit in full - // scale in the alloted space (2 megapixels, so not likely!) + // practice. ati users should disable direct renderering if using the + // #if 0'ed code above. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level); // we don't set min_lod so we can 'DefineLevels' using the old value. GLenum error = glGetError(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -96,8 +96,11 @@ void SetMaxLevel(int level); void Bind(); unsigned int GetNumber() {return num;}; + // if the image has a mask, we want to use alpha blending to draw it. + bool GetUseAlpha() {return has_mask;}; private: unsigned int num; // the openGL texture name + bool has_mask; // this binds a new texture in openGL and sets the various parameters // we need for it. void CreateTexture(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -280,9 +280,7 @@ { vertex_c[0] += view_state->GetProjectionInfo()->GetXAdd360(vertex_c[1]); - } - else - { + } else { vertex_c[0] -= view_state->GetProjectionInfo()->GetXAdd360(vertex_c[1]); } @@ -645,7 +643,6 @@ } break; case HuginBase::PanoramaOptions::SINUSOIDAL: - case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: // like above, but the bounds change with height if ( node->verts[0][0][0] < i->GetLowerX(node->verts[0][0][1]) || node->verts[0][0][0] > i->GetUpperX(node->verts[0][0][1]) @@ -708,6 +705,8 @@ } } break; + case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: + break; } if (noncontinuous) { @@ -753,90 +752,6 @@ node->flags |= split_flag_x | patch_flag_x; } } - /*if (x && !(flags & split_flag_y) && depth < max_depth) - { - // scan back up the tree until we get something with a child node on the - // left not containing this node. - unsigned int nid = node_id, depth_c = 0.0; - while ((nid % 2)) - { - nid = tree.GetParentId(nid); - depth_c ++; - } - // now go back down the tree - unsigned int x2, y2, row_size2, depth2; - tree.GetPosition(nid, x2, y2, row_size2, depth2); - bool y_split = tree.nodes[nid].flags & split_flag_y; - // take the child not containing the node we are testing - x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; - // we'll need to deduce the location in y again. - if (y_split && (y2 != (y >> (depth - depth2)))) y2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; - // now we go right child until we get to the same depth, if there is - // enough splits in y. We also change heights to find the one we want. - for (;depth_c && y_split; depth_c--) - { - x2*=2; y2*=2; - row_size2 *= 2; depth2++; - // move across in x if there is a subdivision, stick to the right: - if ((tree.nodes[nid].flags & split_flag_x)) x2++; - // there will be a split in y, so work out which child gets us - // where we want to be: - if (y2 != (y >> (depth - depth2))) y2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; - } - if (y_split && !(tree.nodes[nid].flags & patch_flag_y)) - { - // more subdivision on the left. - // we want to split just to line up with the other subdivision. - node->flags |= split_flag_y | patch_flag_y; - } - } - // same for the other direction - if (y && !(flags & split_flag_x) && depth < max_depth) - { - // scan back up the tree until we get something with a child node on the - // top not containing this node. - unsigned int nid = node_id, depth_c, row_size2 = row_size; - while ((nid / row_size) % 2) - { - nid = tree.GetParentId(nid); - depth_c ++; - row_size /= 2; - } - // now go back down the tree - unsigned int x2, y2, depth2; - tree.GetPosition(nid, x2, y2, row_size2, depth2); - bool x_split = tree.nodes[nid].flags & split_flag_x; - // take the child not containing the node we are testing - x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; - // we'll need to deduce the location in x again. - if (x_split && (x2 != (x >> (depth - depth2)))) x2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_x)) x_split = false; - // now we take the downward child until we get to the same depth, if - // there is enough splits in x. We also change x location to find the - // one we want. - for (;depth_c && x_split; depth_c--) - { - x2*=2; y2*=2; - row_size2 *= 2; depth2++; - // move down in y if there is a subdivision - if ((tree.nodes[nid].flags & split_flag_y)) y2++; - // there will be a split in x, so find where we are - if (x2 != x >> (depth - depth2)) x2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_x)) x_split = false; - } - if (x_split && !(tree.nodes[nid].flags & patch_flag_x)) - { - // more subdivision on the left. - // we want to split just to line up with the other subdivision. - node->flags |= split_flag_x | patch_flag_x; - } - }*/ } void VertexCoordRemapper::SetLengthAndAngle(TreeNode *node) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-12 23:02:19
|
Revision: 3312 http://hugin.svn.sourceforge.net/hugin/?rev=3312&view=rev Author: jlegg Date: 2008-08-12 23:02:17 +0000 (Tue, 12 Aug 2008) Log Message: ----------- Added missing files from last commit. :-/ Added Paths: ----------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.h Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp 2008-08-12 23:02:17 UTC (rev 3312) @@ -0,0 +1,91 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewPanoMaskTool.cpp + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "PreviewPanoMaskTool.h" +#include <GL/gl.h> + +PreviewPanoMaskTool::PreviewPanoMaskTool(PreviewToolHelper *helper) + : PreviewTool(helper) +{ +} + +void PreviewPanoMaskTool::Activate() +{ + // we draw to the sentcil buffer the desired shape, and enable the stencil + // test before the images are rendered. After they have all been drawn, we + // turn off stenciling so the other tools can draw of the complete area. + helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); +} + +void PreviewPanoMaskTool::BeforeDrawImagesEvent() +{ +} + +void PreviewPanoMaskTool::AfterDrawImagesEvent() +{ + switch (helper->GetViewStatePtr()->GetOptions()->getProjection()) + { + case HuginBase::PanoramaOptions::SINUSOIDAL: + glDisable(GL_TEXTURE_2D); + glColor3f(0.0, 0.0, 0.0); + { + // Under a sinusodial projection, we mask off the sides. + OutputProjectionInfo *info = helper->GetViewStatePtr()-> + GetProjectionInfo(); + double x, y; + glBegin(GL_QUAD_STRIP); + for (double p = -90; p < 90; p += 1.0) + { + info->AngularToImage(x, y, -180.0, p); + glVertex2d(x, y); glVertex2d(0.0, y); + } + glEnd(); + double width = helper->GetViewStatePtr()->GetOptions()-> + getSize().width(); + glBegin(GL_QUAD_STRIP); + for (double p = -90; p < 90; p += 1.0) + { + info->AngularToImage(x, y, -180.0, p); + glVertex2d(width - x, y); glVertex2d(width, y); + } + glEnd(); + } + glEnable(GL_TEXTURE_2D); + glColor3f(1.0, 1.0, 1.0); + break; + case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: + // Under a albers equal area conic projection, we mask a circle + // segment with a hole in the middle. The dimensions and centre + // are depended on the projection parameters. + glDisable(GL_TEXTURE_2D); + glColor3f(0.0, 0.0, 0.0); + glStencilFunc(GL_EQUAL, 1, 1); + glEnable(GL_TEXTURE_2D); + glColor3f(1.0, 1.0, 1.0); + break; + default: + // most projections don't need any of this. + // Always pass the stencil test. + glStencilFunc(GL_ALWAYS, 1, 1); + break; + } +} + Added: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.h (rev 0) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.h 2008-08-12 23:02:17 UTC (rev 3312) @@ -0,0 +1,42 @@ +// -*- c-basic-offset: 4 -*- +/** @file PreviewPanoMaskTool.h + * + * @author James Legg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* For projections where the output range is limited, but the approximatly + * remaped images can extend this, we mask out the off-panorama bits with a + * stencil. + */ + +#ifndef _PREVIEWPANOMASKTOOL_h +#define _PREVIEWPANOMASKTOOL_h + +#include "PreviewTool.h" + +class PreviewPanoMaskTool : public PreviewTool +{ +public: + PreviewPanoMaskTool(PreviewToolHelper *helper); + void Activate(); + void BeforeDrawImagesEvent(); + void AfterDrawImagesEvent(); +}; + +#endif + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-14 03:50:19
|
Revision: 3318 http://hugin.svn.sourceforge.net/hugin/?rev=3318&view=rev Author: jlegg Date: 2008-08-14 03:50:17 +0000 (Thu, 14 Aug 2008) Log Message: ----------- Drag tool now works with the image component containing the topmost drawn image under the mouse (when there is more than one image component in the panorama). With one component, blank space still moves the panorama, but with more components draging blank space has no effect. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-13 20:23:07 UTC (rev 3317) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-14 03:50:17 UTC (rev 3318) @@ -25,11 +25,13 @@ #include "PreviewDragTool.h" #include "CommandHistory.h" -#include "PT/PanoCommand.h" +#include "PT/PanoCommand.h" +#include "PT/ImageGraph.h" #include <math.h> #include <GL/gl.h> + PreviewDragTool::PreviewDragTool(PreviewToolHelper *helper) : PreviewTool(helper) { @@ -170,45 +172,84 @@ { shift_angle = 0.0; // record where the images are so we know what the difference is. - // TODO use the topmost drawn component instead of all of the images - /*std::set<unsigned int> dragging_images - = helper->GetImageNumbersUnderMouse(); - // Record where the images are. - for (std::set<unsigned int>::iterator i = dragging_images.begin(); - i != dragging_images.end(); i++) + // Use the component the mouse points to instead of every image. + // Find the components + PT::CPGraph graph; + PT::createCPGraph(*helper->GetPanoramaPtr(), graph); + PT::CPComponents components; + unsigned int n = PT::findCPComponents(graph, components); + // If there is only component, we can drag everything. Otherwise the + // component we want is the lowest numbered image under the mouse. + if (n == 1) { - image_angles[*i].Set(helper->GetViewStatePtr()-> - GetSrcImage(*i)); - }*/ - unsigned int imgs = helper->GetPanoramaPtr()->getNrOfImages(); - for (unsigned int i = 0; i < imgs; i++) + unsigned int imgs = helper->GetPanoramaPtr()->getNrOfImages(); + fill_set(draging_images, 0, imgs - 1); + ViewState *view_state_ptr = helper->GetViewStatePtr(); + for (unsigned int i = 0; i < imgs; i++) + { + image_angles[i].Set(view_state_ptr->GetSrcImage(i)); + }; + } else { - image_angles[i].Set(helper->GetViewStatePtr()->GetSrcImage(i)); - }; + // multiple components or none at all. + if (n == 0 || helper->GetImageNumbersUnderMouse().empty()) + { + // we can't drag nothing. + drag_roll = false; drag_yaw = false; drag_pitch = false; + return; + } + // Find the component containing the topmost image under mouse + unsigned int img = *helper->GetImageNumbersUnderMouse().begin(); + for (unsigned int component_index = 0; + component_index < components.size(); component_index ++) + { + if (components[component_index].count(img)) + { + // Found it, record which images and where they are. + draging_images = components[component_index]; + std::set<unsigned int>::iterator i, end; + end = draging_images.end(); + for (i = draging_images.begin(); i != end; i++) + { + image_angles[*i].Set( + helper->GetViewStatePtr()->GetSrcImage(*i)); + } + break; + } + } + } SetRotationMatrix(shift_coordinates.x, shift_coordinates.y, shift_angle, start_coordinates.x, start_coordinates.y, 0.0); } } else { - // apply rotations permanently - /*for (std::map<unsigned int, AngleStore> i = image_angles.begin(); - i != image_angles.end(); i++ ) - panorama.updateVariable( i, Variable("y", y) ); - panorama.updateVariable( i, Variable("p", p) ); - panorama.updateVariable( i, Variable("r", r) ); - panorama.imageChanged(i);*/ - // TODO rotate the right stuff when not rotating the entire panorama. - double yaw, pitch, roll; - rotation_matrix.GetRotationPT(yaw, pitch, roll); - yaw = RAD_TO_DEG(yaw); - pitch = RAD_TO_DEG(pitch); - roll = RAD_TO_DEG(roll); + // check this wasn't an attempt to drag empty space. + if (! (drag_pitch || drag_roll || drag_yaw)) return; + + // Finished draging images: + drag_yaw = false; drag_pitch = false; drag_roll = false; + // Apply the rotations permanently. + // find where the images end up. + std::vector<HuginBase::SrcPanoImage> src_images(draging_images.size() + 1); + std::map<unsigned int, AngleStore>::iterator i; + unsigned int count = 0; + for (i = image_angles.begin(); i != image_angles.end(); i++) + { + double nyaw, npitch, nroll; + i->second.Move(&rotation_matrix, nyaw, npitch, nroll); + src_images[count] = helper->GetPanoramaPtr()->getSrcImage(i->first); + src_images[count].setYaw(nyaw); + src_images[count].setPitch(npitch); + src_images[count].setRoll(nroll); + count++; + } GlobalCmdHist::getInstance().addCommand( - new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), - yaw, pitch, roll), true); + new PT::UpdateSrcImagesCmd(*helper->GetPanoramaPtr(), + draging_images, + src_images) + ); // stop dragging image_angles.clear(); - drag_yaw = false; drag_pitch = false; drag_roll = false; helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or ctrl-drag.")); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-13 20:23:07 UTC (rev 3317) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-14 03:50:17 UTC (rev 3318) @@ -63,6 +63,7 @@ }; private: std::map<unsigned int, AngleStore> image_angles; + std::set<unsigned int> draging_images; bool drag_yaw, drag_pitch, drag_roll; double start_angle, shift_angle; hugin_utils::FDiff2D centre, start_coordinates, shift_coordinates; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-15 01:38:50
|
Revision: 3319 http://hugin.svn.sourceforge.net/hugin/?rev=3319&view=rev Author: jlegg Date: 2008-08-15 01:38:46 +0000 (Fri, 15 Aug 2008) Log Message: ----------- Removed the LDR/HDR mode selection from the preview window, since HDR display is not implemented. A few fixes for compiling on windows: extra #includes, reworkings for Microsoft's compiler, and renaming Polygon in MeshRemapper.cpp to A_Polygon to avoid conflicts. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-15 01:38:46 UTC (rev 3319) @@ -102,7 +102,7 @@ EVT_SPIN_UP(ID_EXPOSURE_SPIN, GLPreviewFrame::OnIncreaseExposure) EVT_CHOICE(ID_BLEND_CHOICE, GLPreviewFrame::OnBlendChoice) EVT_CHOICE(ID_PROJECTION_CHOICE, GLPreviewFrame::OnProjectionChoice) - EVT_CHOICE(ID_OUTPUTMODE_CHOICE, GLPreviewFrame::OnOutputChoice) + // EVT_CHOICE(ID_OUTPUTMODE_CHOICE, GLPreviewFrame::OnOutputChoice) EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV) EVT_SCROLL_THUMBTRACK(GLPreviewFrame::OnTrackChangeFOV) END_EVENT_TABLE() @@ -275,6 +275,8 @@ 5); // TODO implement hdr display in OpenGL, if possible? + // Disabled until someone can figure out HDR display in OpenGL. + /* ////////////////////////////////////////////////////// // LDR, HDR blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")), @@ -292,7 +294,8 @@ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); - + */ + ///////////////////////////////////////////////////// // exposure blendModeSizer->Add(new wxStaticText(this, -1, _("EV:")), @@ -439,23 +442,21 @@ wxString projection; m_ProjectionChoice->SetSelection(opts.getProjection()); m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) ); - + + // No HDR display yet. + /* m_outputModeChoice->SetSelection(opts.outputMode); if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) { - /* m_exposureTextCtrl->Hide(); m_defaultExposureBut->Hide(); m_decExposureBut->Hide(); m_incExposureBut->Hide(); - */ } else { - /* m_exposureTextCtrl->Show(); m_defaultExposureBut->Show(); m_decExposureBut->Show(); m_incExposureBut->Show(); - */ - } + }*/ m_exposureTextCtrl->SetValue(wxString(doubleToString(opts.outputExposureValue,2).c_str(), wxConvLocal)); bool activeImgs = pano.getActiveImages().size() > 0; @@ -913,6 +914,7 @@ } } +/* We don't have an OpenGL hdr display yet void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e) { if (e.GetEventObject() == m_outputModeChoice) { @@ -928,6 +930,7 @@ // FIXME DEBUG_WARN("wxChoice event from unknown object received"); } } +*/ /** update the display */ void GLPreviewFrame::updateProgressDisplay() Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-15 01:38:46 UTC (rev 3319) @@ -124,7 +124,8 @@ void OnBlendChoice(wxCommandEvent & e); void OnProjectionChoice(wxCommandEvent & e); - void OnOutputChoice(wxCommandEvent & e); + // No HDR display yet + // void OnOutputChoice(wxCommandEvent & e); // update the panorama display void updatePano(); @@ -139,7 +140,8 @@ wxSlider * m_VFOVSlider; wxChoice * m_BlendModeChoice; wxChoice * m_ProjectionChoice; - wxChoice * m_outputModeChoice; + // No HDR display yet. + // wxChoice * m_outputModeChoice; wxTextCtrl * m_exposureTextCtrl; wxBitmapButton * m_defaultExposureBut; wxSpinButton * m_exposureSpinBut; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-15 01:38:46 UTC (rev 3319) @@ -21,6 +21,8 @@ #include <config.h> #include <GL/glew.h> +#include "hugin_utils/utils.h" +#include <base_wx/platform.h> #include <wx/settings.h> #include <wx/dcclient.h> #include <wx/event.h> Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-08-15 01:38:46 UTC (rev 3319) @@ -25,6 +25,7 @@ #define _GL_VIEWER_H #include "ViewState.h" +#include "base_wx/platform.h" #include <wx/glcanvas.h> #include <utility> #include <vigra/diff2d.hxx> Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-08-15 01:38:46 UTC (rev 3319) @@ -104,17 +104,18 @@ tex_c[1] = ty; } -// The Polygon class stores an arbitrary polygon, and can give you another +// The A_Polygon class stores an arbitrary polygon, and can give you another // polygon that is the result of clipping it with some line. -class Polygon +// hmmm... Using the name "Polygon" causes errors on windows, hence A_Polgon. +class A_Polygon { public: // Create the polygon from a quadrilateral - Polygon(MeshRemapper::Coords *face); - Polygon() {} + A_Polygon(MeshRemapper::Coords *face); + A_Polygon() {} // clip lines are the line defined by x * p[0] + y * p[1] + p[2] = 0. // inside is the side where x * p[0] + y *p[1] + p[2] > 0. - Polygon Clip(const double clip_line[3]); + A_Polygon Clip(const double clip_line[3]); // add a vertex on the end of the list. Used to build the polygon when not // created from a quad. inline void AddVertex(Vertex v); @@ -132,7 +133,7 @@ const double clip_line[3]) const; }; -Polygon::Polygon(MeshRemapper::Coords *face) +A_Polygon::A_Polygon(MeshRemapper::Coords *face) { verts.resize(4); for (unsigned short int v = 0; v < 4; v++) @@ -148,17 +149,17 @@ } } -inline void Polygon::AddVertex(Vertex v) +inline void A_Polygon::AddVertex(Vertex v) { verts.push_back(v); } -inline bool Polygon::Inside(const unsigned int v, const double l[3]) const +inline bool A_Polygon::Inside(const unsigned int v, const double l[3]) const { return verts[v].tex_c[0] * l[0] + verts[v].tex_c[1] * l[1] + l[2] > 0; } -Vertex Polygon::Intersect(const unsigned int v1_index, +Vertex A_Polygon::Intersect(const unsigned int v1_index, const unsigned int v2_index, const double cl[3]) const { @@ -199,11 +200,11 @@ return Vertex(xc, yc, x, y); } -Polygon Polygon::Clip(const double clip_line[3]) +A_Polygon A_Polygon::Clip(const double clip_line[3]) { // We'll use the Sutherland-Hodgman clipping algorithm. // see http://en.wikipedia.org/wiki/Sutherland-Hodgeman - Polygon result; + A_Polygon result; unsigned int vertices_count = verts.size(), v_previous = vertices_count - 1; // we want to examine all edges in turn, and find the vertices to keep: @@ -226,7 +227,7 @@ return result; } -std::vector<MeshRemapper::ArrayCoords> Polygon::ConvertToQuads() +std::vector<MeshRemapper::ArrayCoords> A_Polygon::ConvertToQuads() { // we want to convert any old polygon to quadrilaterals. /* If the input was from a TexCoordRemapper, we'll have a rectangle with @@ -307,7 +308,7 @@ // vertices locations accordingly. // convert the face to a polygon: - Polygon poly(face); + A_Polygon poly(face); // work out where the clipping lines are, we use the cropping rectangle: double clip_lines[4][3] = {{ 1.0, 0.0, -crop_x1}, {-1.0, 0.0, crop_x2}, Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-08-15 01:38:46 UTC (rev 3319) @@ -28,6 +28,7 @@ #ifndef _PREVIEWTOOL_H #define _PREVIEWTOOL_H +#include "hugin_utils/utils.h" #include <wx/event.h> #include "PreviewToolHelper.h" Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-15 01:38:46 UTC (rev 3319) @@ -47,6 +47,8 @@ #ifndef _PREVIEWTOOLHELPER_H #define _PREVIEWTOOLHELPER_H +#include "hugin_utils/utils.h" +#include "base_wx/platform.h" #include <wx/defs.h> #include <wx/event.h> #include <wx/string.h> Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-15 01:38:46 UTC (rev 3319) @@ -26,10 +26,6 @@ // The OpenGL Extension wrangler libray will find extensions and the latest // supported OpenGL version on all platforms. #include <GL/glew.h> -// include OpenGL's GL and GLU headers on all platforms, but there are some -// minor diffferences, uses wxwidgets for platform detection: -#include <wx/wx.h> -#include <wx/platform.h> #include <GL/gl.h> #include <GL/glu.h> @@ -340,7 +336,7 @@ // check if this is over budget. ideal_texels_used += ideal_texels; // while the texture is over budget, shrink it - while ( (texels_used + 1 << (tex_width_p + tex_height_p)) + while ( (texels_used + (1 << (tex_width_p + tex_height_p))) > ideal_texels_used) { // smaller aspect means the texture is wider. @@ -669,23 +665,30 @@ if (has_mask) { // combine the alpha bitmap with the red green and blue one. - unsigned char image[ho][wo][4]; + unsigned char *image = new unsigned char[ho * wo * 4]; + unsigned char *pix_start = image; for (int h = 0; h < ho; h++) { for (int w = 0; w < wo; w++) { - image[h][w][0] = out_img[h][w].red(); - image[h][w][1] = out_img[h][w].green(); - image[h][w][2] = out_img[h][w].blue(); - image[h][w][3] = out_alpha[h][w]; + pix_start += 4; + pix_start[0] = out_img[h][w].red(); + pix_start[1] = out_img[h][w].green(); + pix_start[2] = out_img[h][w].blue(); + pix_start[3] = out_alpha[h][w]; } } - error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGBA8, wo, ho, - GL_RGBA, GL_UNSIGNED_BYTE, min, min, max, image); + // We don't need to worry about levels with the ATI bug work around, + // and Windows doesn't like it as gluBuild2DMipmapLevels is in OpenGL + // version 1.3 and above only (Microsoft's SDK only uses 1.1) + error = gluBuild2DMipmaps/*Levels*/(GL_TEXTURE_2D, GL_RGBA8, wo, ho, + GL_RGBA, GL_UNSIGNED_BYTE, /*min, min, max,*/ + image); + delete [] image; } else { // we don't need to rearange the data in memory if there is no mask. - error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, wo, ho, - GL_RGB, GL_UNSIGNED_BYTE, min, min, max, + error = gluBuild2DMipmaps/*Levels*/(GL_TEXTURE_2D, GL_RGB8, wo, ho, + GL_RGB, GL_UNSIGNED_BYTE, /*min, min, max,*/ (unsigned char *) out_img.data()); } if (error) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-08-14 03:50:17 UTC (rev 3318) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ViewState.h 2008-08-15 01:38:46 UTC (rev 3319) @@ -49,6 +49,7 @@ #ifndef __VIEWSTATE_H #define __VIEWSTATE_H +#include "hugin_utils/utils.h" #include <panodata/PanoramaData.h> #include <panodata/Panorama.h> #include "PT/Panorama.h" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jl...@us...> - 2008-08-26 18:31:18
|
Revision: 3363 http://hugin.svn.sourceforge.net/hugin/?rev=3363&view=rev Author: jlegg Date: 2008-08-26 18:31:14 +0000 (Tue, 26 Aug 2008) Log Message: ----------- Fixes for OS X. wxWidget's wxGLCanvas has different features depending on platform, this commit allows it to works with wxMac's feature set. A few #includes were reordered to fix a OS X specific error in src/foreign/vigra/vigra/static_assert.hxx. I've taken account for OpenGL's headers being in a different directory on OS X to windows and linux. The textures for the indentify tool came out black, so I've worked around the problem, using a little more memory and time to start the preview. Also the button colours for the identify tool did not work, but the colours work as backgrounds for checkboxes, so I switched back to using them for the displayed images. The sliders don't work properly, but they didn't when the project was branched so hopefully I'll get them fixed when merging this branch with gsoc2008_integration. It crashes when closed too, I don't know the cause of that. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -24,10 +24,10 @@ // use toggle buttons or uncomment check boxes -//#ifndef __WXMAC__ +#ifndef __WXMAC__ #define USE_TOGGLE_BUTTON 1 -//#endif -//wxMac now has toggle buttons. +#endif +//wxMac now has toggle buttons, but you can't overide their colours. #include <config.h> @@ -1075,15 +1075,24 @@ unsigned char green, unsigned char blue) { + // 0, 0, 0 indicates we want to go back to the system colour. + // TODO: Maybe we should test this better on different themes. + // On OS X, the background colour is ignored on toggle buttons, but not + // checkboxes. if (red || green || blue) { // the identify tool wants us to highlight an image button in the given // colour, to match up with the display in the preview. + m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR); m_ToggleButtons[image_nr]->SetBackgroundColour( wxColour(red, green, blue)); + // black should be visible on the button's vibrant colours. + m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0)); } else { // return to the normal colour + m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM); m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour); + m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour); } m_ToggleButtons[image_nr]->Refresh(); } @@ -1096,7 +1105,10 @@ unsigned int nr_images = m_pano.getNrOfImages(); for (unsigned image = 0; image < nr_images; image++) { + m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM); m_ToggleButtons[image]->SetBackgroundColour(wxNullColour); + m_ToggleButtons[image]->SetForegroundColour(wxNullColour); + m_ToggleButtons[image]->Refresh(); } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -26,15 +26,8 @@ #include <OpenGL/gl.h> #else #ifdef __WXMSW__ -#ifndef NOMINMAX -#define NOMINMAX +#include <vigra/windows.h> #endif -#include <windows.h> -#undef NOMINMAX -#ifdef DIFFERENCE -#undef DIFFERENCE -#endif -#endif #include <GL/gl.h> #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -19,16 +19,14 @@ * */ +#include "panoinc.h" #include <config.h> #include <GL/glew.h> -#include "hugin_utils/utils.h" #include <base_wx/platform.h> #include <wx/settings.h> #include <wx/dcclient.h> #include <wx/event.h> -#include "panoinc.h" - #include "GLViewer.h" #include "GLRenderer.h" #include "TextureManager.h" @@ -55,10 +53,17 @@ END_EVENT_TABLE() GLViewer::GLViewer(wxFrame* parent, PT::Panorama &pano, int args[], GLPreviewFrame *frame_in) : - wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, - 0, wxT("GLPreviewCanvas"), wxNullPalette) + wxGLCanvas(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, + 0, wxT("GLPreviewCanvas"), args, wxNullPalette) { - m_glContext = new wxGLContext(this, 0); + /* The openGL display context doesn't seem to be created automatically on + * wxGTK, and on wxMac the constructor doesn't fit the documentation. I + * create a new context on anything but wxMac and hope it works... */ + #ifdef __WXMAC__ + m_glContext = GetContext(); + #else + m_glContext = new wxGLContext(this, 0); + #endif m_renderer = 0; @@ -85,7 +90,11 @@ // set the context std::cout << "Setting rendering context:\n"; Show(); + #ifdef __WXMAC__ + m_glContext->SetCurrent(); + #else m_glContext->SetCurrent(*this); + #endif std::cout << "OK\n"; if (!started_creation) { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -20,15 +20,21 @@ * */ +#include "panoinc_WX.h" +#include "panoinc.h" #include "PreviewCropTool.h" #include <config.h> -#include "panoinc_WX.h" -#include "panoinc.h" #include "base_wx/platform.h" #include "hugin/config_defaults.h" #include "CommandHistory.h" #include "wxPanoCommand.h" + +#include <wx/platform.h> +#ifdef __WXMAC__ +#include <OpenGL/gl.h> +#else #include <GL/gl.h> +#endif PreviewCropTool::PreviewCropTool(PreviewToolHelper *helper) : PreviewTool(helper) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -21,7 +21,12 @@ #include "PreviewDifferenceTool.h" #include <GL/glew.h> +#include <wx/platform.h> +#ifdef __WXMAC__ +#include <OpenGL/gl.h> +#else #include <GL/gl.h> +#endif // This is the number of times to double the result of the difference. It should // be between 0 and 7. Note that with values > 0 no extra colours are used Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -26,12 +26,16 @@ #include "PreviewDragTool.h" #include "CommandHistory.h" #include "PT/PanoCommand.h" -#include "PT/ImageGraph.h" +#include "PT/ImageGraph.h" #include <math.h> +#include <wx/platform.h> +#ifdef __WXMAC__ +#include <OpenGL/gl.h> +#else #include <GL/gl.h> +#endif - PreviewDragTool::PreviewDragTool(PreviewToolHelper *helper) : PreviewTool(helper) { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -19,19 +19,24 @@ * */ +#include "panoinc_WX.h" +#include "panoinc.h" + #include "PreviewIdentifyTool.h" #include <config.h> -#include "panoinc_WX.h" - -#include "panoinc.h" - #include "base_wx/platform.h" #include "GLPreviewFrame.h" #include "MainFrame.h" +#include <wx/platform.h> +#ifdef __WXMAC__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else #include <GL/gl.h> #include <GL/glu.h> +#endif #include <algorithm> #include <vector> @@ -54,43 +59,52 @@ preview_frame = owner; // make the textures. We have a circle border and a square one. // the textures are white with a the alpha chanel forming a border. - glGenTextures(1, &rectangle_border_tex); - glGenTextures(1, &circle_border_tex); + glGenTextures(1, (GLuint*) &rectangle_border_tex); + glGenTextures(1, (GLuint*) &circle_border_tex); // we only want to specify alpha, but using just alpha in opengl attaches 0 - // for the luminosity. We'll bias rgb values to get 1.0, so we can colour - // the texture in something other than black: - glPixelTransferf(GL_RED_BIAS, 1.0); - glPixelTransferf(GL_GREEN_BIAS, 1.0); - glPixelTransferf(GL_BLUE_BIAS, 1.0); + // for the luminosity. I tried biasing the red green and blue values to get + // them to 1.0, but it didn't work under OS X for some reason. Instead we + // use a luminance alpha pair, and use 1.0 for luminance all the time. { // In the rectangle texture, the middle is 1/4 opaque, the outer pixels // are completely transparent, and one pixel in from the edges is // a completly opaque line. - unsigned char rect_tex_data[rect_ts][rect_ts]; - for (unsigned int x = 2; x < rect_ts-2; x++) + unsigned char rect_tex_data[rect_ts][rect_ts][2]; + // make everything white + for (unsigned int x = 0; x < rect_ts; x++) { + for (unsigned int y = 0; y < rect_ts; y++) + { + rect_tex_data[x][y][0] = 255; + } + } + // now set the middle of the mask semi transparent + for (unsigned int x = 2; x < rect_ts - 2; x++) + { for (unsigned int y = 2; y < rect_ts - 2; y++) { - rect_tex_data[x][y] = 63; + rect_tex_data[x][y][1] = 63; } } + // make an opaque border for (unsigned int d = 1; d < rect_ts - 1; d++) { - rect_tex_data[d][1] = 255; - rect_tex_data[d][rect_ts - 2] = 255; - rect_tex_data[1][d] = 255; - rect_tex_data[rect_ts - 2][d] = 255; + rect_tex_data[d][1][1] = 255; + rect_tex_data[d][rect_ts - 2][1] = 255; + rect_tex_data[1][d][1] = 255; + rect_tex_data[rect_ts - 2][d][1] = 255; } + // make a transparent border around that for (unsigned int d = 0; d < rect_ts; d++) { - rect_tex_data[d][0] = 0; - rect_tex_data[d][rect_ts - 1] = 0; - rect_tex_data[0][d] = 0; - rect_tex_data[rect_ts - 1][d] = 0; + rect_tex_data[d][0][1] = 0; + rect_tex_data[d][rect_ts - 1][1] = 0; + rect_tex_data[0][d][1] = 0; + rect_tex_data[rect_ts - 1][d][1] = 0; } glBindTexture(GL_TEXTURE_2D, rectangle_border_tex); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, rect_ts, rect_ts, - GL_ALPHA, GL_UNSIGNED_BYTE, rect_tex_data); + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rect_tex_data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } @@ -99,7 +113,7 @@ // enlarge it so that the circle apears less blocky. We don't want to // make it equally sharper however, so we make it a bit fuzzier by // blending. - unsigned char circle_tex_data[circle_ts][circle_ts]; + unsigned char circle_tex_data[circle_ts][circle_ts][2]; for (unsigned int x = 0; x < circle_ts; x++) { for (unsigned int y = 0; y < circle_ts; y++) @@ -123,26 +137,23 @@ { intensity = 0.0; } - circle_tex_data[x][y] = (unsigned char) intensity; + circle_tex_data[x][y][0] = 255; + circle_tex_data[x][y][1] = (unsigned char) intensity; } } glBindTexture(GL_TEXTURE_2D, circle_border_tex); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, circle_ts, circle_ts, - GL_ALPHA, GL_UNSIGNED_BYTE, circle_tex_data); + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, circle_tex_data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } - // set these back as expected. - glPixelTransferf(GL_RED_BIAS, 0.0); - glPixelTransferf(GL_GREEN_BIAS, 0.0); - glPixelTransferf(GL_BLUE_BIAS, 0.0); } PreviewIdentifyTool::~PreviewIdentifyTool() { // free the textures - glDeleteTextures(1, &rectangle_border_tex); - glDeleteTextures(1, &circle_border_tex); + glDeleteTextures(1, (GLuint*) &rectangle_border_tex); + glDeleteTextures(1, (GLuint*) &circle_border_tex); } void PreviewIdentifyTool::Activate() Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewPanoMaskTool.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -20,7 +20,12 @@ */ #include "PreviewPanoMaskTool.h" +#include <wx/platform.h> +#ifdef __WXMAC__ +#include <OpenGL/gl.h> +#else #include <GL/gl.h> +#endif PreviewPanoMaskTool::PreviewPanoMaskTool(PreviewToolHelper *helper) : PreviewTool(helper) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-26 05:44:10 UTC (rev 3362) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-26 18:31:14 UTC (rev 3363) @@ -23,26 +23,28 @@ #include <math.h> #include <iostream> -// The OpenGL Extension wrangler libray will find extensions and the latest -// supported OpenGL version on all platforms. -#include <GL/glew.h> -#include <GL/gl.h> -#include <GL/glu.h> - #include <config.h> -//#include "panoinc_WX.h" -//#include "panoinc.h" #include "ViewState.h" #include "TextureManager.h" #include "vigra/stdimage.hxx" #include "vigra/resizeimage.hxx" -#include "vigra/impex.hxx" -//#include <vigra_ext/Pyramid.h> #include "base_wx/ImageCache.h" #include "photometric/ResponseTransform.h" +// The OpenGL Extension wrangler libray will find extensions and the latest +// supported OpenGL version on all platforms. +#include <GL/glew.h> +#include <wx/platform.h> +#ifdef __WXMAC__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif + TextureManager::TextureManager(PT::Panorama *pano, ViewState *view_state_in) { m_pano = pano; @@ -486,10 +488,10 @@ void TextureManager::TextureInfo::CreateTexture() { // Get an number for an OpenGL texture - glGenTextures(1, &num); + glGenTextures(1, (GLuint*) &num); // we want to generate all levels of detail, they are all undefined. min_lod = 1000; - glBindTexture(GL_TEXTURE_2D, num); + glBindTexture(GL_TEXTURE_2D, (GLuint) num); SetParameters(); } @@ -539,7 +541,7 @@ TextureManager::TextureInfo::~TextureInfo() { // free up the graphics system's memory for this texture - glDeleteTextures(1, &num); + glDeleteTextures(1, (GLuint*) &num); } void TextureManager::TextureInfo::Bind() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |