// // File: texture_image_window.cc // // (C) 2000-2006 Helmut Cantzler // // Licensed under the terms of the Lesser General Public License. // #include #include #include #include #include "texture_image.h" #include "mview.h" TextureImageWindow::TextureImageWindow(MView *parent, GLMesh *glmesh, Mesh *mesh) : QMainWindow(parent) { TextureImageWindow::glmesh = glmesh; TextureImageWindow::mesh = mesh; TextureImageWindow::parent = parent; QVBox *box = new QVBox(this); box->setMargin(5); box->setSpacing(5); setCentralWidget( box ); QScrollView *sv = new QScrollView(box); img = new TextureImage(this); sv->addChild(img); QWidget *buttons = new QWidget(box); QHBoxLayout *buttons_layout = new QHBoxLayout(buttons); buttons_layout->setMargin(5); buttons_layout->setSpacing(5); QPushButton *load = new QPushButton("Load", buttons); connect(load, SIGNAL(clicked()), img, SLOT(loadImage())); QPushButton *mapping = new QPushButton("Map", buttons); connect(mapping, SIGNAL(clicked()), this, SLOT(texture_mapping())); QPushButton *clear = new QPushButton("Clear", buttons); connect(clear, SIGNAL(clicked()), this, SLOT(clearSelection())); QPushButton *close = new QPushButton("Close", buttons); connect(close, SIGNAL(clicked()), parent, SLOT(closeText())); close->setFocus(); buttons_layout->addStretch( 10 ); buttons_layout->addWidget( load ); buttons_layout->addWidget( mapping ); buttons_layout->addWidget( clear ); buttons_layout->addWidget( close ); resize(450, 350); setCaption("Texture Image"); } void TextureImageWindow::clearSelection(void) { glmesh->clearSelection(); img->clearImage(); } void TextureImageWindow::calc_projection(float *v, Gan_Matrix33 *h, float *x, float *y) { float z; *x = h->xx * v[0] + h->xy * v[1] + h->xz; *y = h->yx * v[0] + h->yy * v[1] + h->yz; z = h->zx * v[0] + h->zy * v[1] + h->zz; *x /= z; *y /= z; } int TextureImageWindow::texture_mapping(void) { // we need: // image size (img_width & img_height) // 4 points on the image (img_pnts) // 4 vertices in the mesh (selected_vertices) list::iterator iv; list::iterator it; Shape *s = NULL; Vertex *v[4]; int s_nr, i; const unsigned int *img_pnts = img->getHomoPoints(); const char *img_name = img->getFileName(); int img_width = img->width(); int img_height = img->height(); if (img_pnts == NULL) return -1; // not enough mesh points ? if (mesh->selected_vertices.size() != 4) return -2; // find shape we want to map the texture onto // all four points must belong to the shape for (s_nr=0; s == NULL && s_nr < mesh->number_of_shapes(); s_nr++) if ( mesh->get_shape(s_nr)->contains(&mesh->selected_vertices) ) s=mesh->get_shape(s_nr); s_nr--; // no shape found ? if (s == NULL) return -3; for (i=0, iv=mesh->selected_vertices.begin(); i < 4; i++, iv++) v[i] = *iv; Gan_Vector3 pnt_img, pnt_mesh; int iEqCount=0; // declare & initialise eigensystem matrix Gan_SymMatEigenStruct SymEigen; gan_homog33_init(&SymEigen); Triangle tri(v[0], v[1], v[2]); MathVector z_axis(0, 0, 1); Quaternion q(tri.math_normal(), &z_axis); for (i=0; i < 4; i++) { pnt_img.x = *img_pnts++; pnt_img.y = *img_pnts++; pnt_img.z = 1.0; const MathVector *from = v[i]->math_data(); MathVector to = q.rotate(from); pnt_mesh.x = to.v[0]; pnt_mesh.y = to.v[1]; pnt_mesh.z = 1.0; // increment matrix using point correspondence gan_homog33_increment_p(&SymEigen, &pnt_mesh, &pnt_img, 1.0, &iEqCount); } // homography matrix Gan_Matrix33 *h = new Gan_Matrix33; gan_homog33_solve(&SymEigen, iEqCount, h); gan_homog33_free(&SymEigen); float x, y; // go over all vertices of the shape and calculate the image position for (it=s->triangles->begin(); it != s->triangles->end(); it++) for (i=0; i < 3; i++) { const MathVector *from = (*it)->vertices[i]->math_data(); MathVector to = q.rotate(from); calc_projection(to.v, h, &x, &y); x = x / img_width; y = 1.0 - y / img_height; if (x < 0.0) x = 0.0; if (x > 1.0) x = 1.0; if (y < 0.0) y = 0.0; if (y > 1.0) y = 1.0; (*it)->set_text_coordinates( i, x, y ); } s->set_texture_name(img_name); glmesh->setShapeTexture(s_nr); parent->displayTexture(); return 0; }