~ubuntu-branches/ubuntu/lucid/meshlab/lucid

« back to all changes in this revision

Viewing changes to meshlab/src/meshlabplugins/edit_phototexturing/src/PhotoTexturer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Teemu Ikonen
  • Date: 2009-10-08 16:40:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20091008164041-0c2ealqv8b8uc20c
Tags: 1.2.2-1
* New upstream version
* Do not build filter_isoparametrization because liblevmar dependency
  is not (yet) in Debian
* Fix compilation with gcc-4.4, thanks to Jonathan Liu for the patch
  (closes: #539544)
* rules: Add compiler variables to the qmake call (for testing with new
  GCC versions)
* io_3ds.pro: Make LIBS and INCLUDEPATH point to Debian version of lib3ds
* io_epoch.pro: Make LIBS point to Debian version of libbz2
* control:
  - Move Homepage URL to the source package section
  - Update to standards-version 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
* MeshLab                                                           o o     *
 
3
* A versatile mesh processing toolbox                             o     o   *
 
4
*                                                                _   O  _   *
 
5
* Copyright(C) 2005                                                \/)\/    *
 
6
* Visual Computing Lab                                            /\/|      *
 
7
* ISTI - Italian National Research Council                           |      *
 
8
*                                                                    \      *
 
9
* All rights reserved.                                                      *
 
10
*                                                                           *
 
11
* This program is free software; you can redistribute it and/or modify      *
 
12
* it under the terms of the GNU General Public License as published by      *
 
13
* the Free Software Foundation; either version 2 of the License, or         *
 
14
* (at your option) any later version.                                       *
 
15
*                                                                           *
 
16
* This program is distributed in the hope that it will be useful,           *
 
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 
19
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
 
20
* for more details.                                                         *
 
21
*                                                                           *
 
22
****************************************************************************/
 
23
 
 
24
#include <cfloat>
 
25
#include <iostream>
 
26
#include <QtGui>
 
27
#include <QImage>
 
28
#include <QMap>
 
29
#include <QColor>
 
30
 
 
31
#include <QtXml/QDomDocument>
 
32
#include <QtXml/QDomElement>
 
33
#include <QtXml/QDomNode>
 
34
 
 
35
#include <src/PhotoTexturer.h>
 
36
#include <src/UVFaceTexture.h>
 
37
#include <src/CameraCalibration.h>
 
38
#include <src/TextureFilter.h>
 
39
#include <src/TextureMerger.h>
 
40
#include <src/Tsai/TsaiCameraCalibration.h>
 
41
 
 
42
#include<vcg/complex/trimesh/allocate.h>
 
43
#include <vcg/math/matrix44.h>
 
44
#include <src/QuadTree/QuadTreeNode.h>
 
45
 
 
46
#include "photo_texture_tools.h"
 
47
 
 
48
#include <src/WinnerTakesAllTextureMerger.h>
 
49
#include <src/SmartBlendTextureMerger.h>
 
50
 
 
51
 
 
52
#include <vcg/complex/trimesh/update/position.h>
 
53
#include <vcg/complex/trimesh/update/bounding.h>
 
54
 
 
55
 
 
56
 
 
57
const QString PhotoTexturer::XML_PHOTOTEXTURING = "photoTexturing";
 
58
 
 
59
//const std::string PhotoTexturer::ORIGINALUVTEXTURECOORDS = "OriginalUVTextureCoords";
 
60
const std::string PhotoTexturer::UVTEXTURECOORDS = "UVTextureCoords";
 
61
 
 
62
const QString PhotoTexturer::TEXTURE_SIZE_WIDTH = "pt_texture_width";
 
63
const QString PhotoTexturer::TEXTURE_SIZE_HEIGHT = "pt_texture_height";
 
64
 
 
65
const QString PhotoTexturer::UNPROJECT_ENABLE_ANGLE = "pt_enable_angle";
 
66
const QString PhotoTexturer::UNPROJECT_ANGLE = "pt_angle";
 
67
const QString PhotoTexturer::UNPROJECT_ANGLE_WEIGHT = "pt_angle_weight";
 
68
const QString PhotoTexturer::UNPROJECT_ANGLE_SHARPNESS = "pt_angle_sharpness";
 
69
 
 
70
const QString PhotoTexturer::UNPROJECT_ENABLE_DISTANCE = "pt_enable_distance";
 
71
const QString PhotoTexturer::UNPROJECT_DISTANCE_WEIGHT = "pt_distance_weight";
 
72
const QString PhotoTexturer::UNPROJECT_DISTANCE_SHARPNESS = "pt_distance_shjarpness";
 
73
 
 
74
const QString PhotoTexturer::UNPROJECT_ENABLE_EDGE_STRETCHING = "pt_enable_edge_stretching";
 
75
const QString PhotoTexturer::UNPROJECT_EDGE_STRETCHING_PASS = "pt_edge_stretching_pass";
 
76
 
 
77
const QString PhotoTexturer::UNPROJECT_TEXTURE_FILENAME = "pt_unproject_texture_name";
 
78
 
 
79
 
 
80
const QString PhotoTexturer::BAKE_SAVE_UNPROJECT = "pt_save_unproject";
 
81
 
 
82
const QString PhotoTexturer::BAKE_MERGE_TEXTURES = "pt_merge_textures";
 
83
const QString PhotoTexturer::BAKE_MERGE_TYPE = "pt_merge_type";
 
84
const QString PhotoTexturer::BAKE_MERGED_TEXTURE = "pt_merged_texture_file";
 
85
const QString PhotoTexturer::BAKE_SMARTBLEND = "pt_smartblend_command";
 
86
 
 
87
#define ZB_EPSILON 1e-2
 
88
 
 
89
 
 
90
PhotoTexturer::PhotoTexturer(){
 
91
        origTextureID = -1;
 
92
        nextTextId = 0;
 
93
        bakeCounter = 0;
 
94
        combineCounter = 0;
 
95
}
 
96
PhotoTexturer::~PhotoTexturer(){
 
97
 
 
98
}
 
99
 
 
100
void PhotoTexturer::loadConfigurationFile(QString cfgFile){
 
101
 
 
102
        QDomDocument doc;
 
103
        cameras.clear();
 
104
        QFile file(cfgFile);
 
105
        QString errorMessage;
 
106
        if (file.open(QIODevice::ReadOnly) && doc.setContent(&file, &errorMessage)){
 
107
                file.close();
 
108
                QDomElement root = doc.documentElement();
 
109
                if (root.nodeName() == XML_PHOTOTEXTURING){
 
110
                        for(QDomElement element = root.firstChildElement(Camera::XML_CAMERA); !element.isNull(); element = element.nextSiblingElement(Camera::XML_CAMERA)){
 
111
                                Camera* cam = new Camera();
 
112
                                cam->loadFromXml(&element);
 
113
                                cameras.push_back(cam);
 
114
                        }
 
115
                }
 
116
        }
 
117
}
 
118
 
 
119
int PhotoTexturer::generateTextureId(){
 
120
        return ++nextTextId;
 
121
}
 
122
 
 
123
void PhotoTexturer::saveConfigurationFile(QString cfgFile){
 
124
        QDomDocument doc(XML_PHOTOTEXTURING);
 
125
        QDomElement root = doc.createElement(XML_PHOTOTEXTURING);
 
126
        doc.appendChild(root);
 
127
 
 
128
        int i;
 
129
        for (i=0;i<cameras.size();i++){
 
130
 
 
131
                Camera *cam = cameras.at(i);
 
132
                cam->saveAsXml(&doc,&root);
 
133
        }
 
134
 
 
135
 
 
136
        QFile file(cfgFile);
 
137
        file.open(QIODevice::WriteOnly);
 
138
        QTextStream qstream(&file);
 
139
        doc.save(qstream,1);
 
140
        file.close();
 
141
}
 
142
 
 
143
void PhotoTexturer::addCamera(QString camFile){
 
144
        QDomDocument doc;
 
145
        QFile file(camFile);
 
146
        QString errorMessage;
 
147
        
 
148
        if (file.open(QIODevice::ReadOnly) && doc.setContent(&file, &errorMessage)){
 
149
                file.close();
 
150
                QDomElement root = doc.documentElement();
 
151
                qDebug() << root.nodeName() ;
 
152
                if (root.nodeName() == Camera::XML_CAMERADOCUMENT){
 
153
                        
 
154
                        QDomElement xml_cam = root.firstChildElement(Camera::XML_CAMERA);
 
155
                        if (!xml_cam.isNull()){
 
156
                                                Camera* cam = new Camera();
 
157
                                                cam->loadFromXml(&xml_cam);
 
158
                                                cameras.push_back(cam);
 
159
                        }
 
160
                }else{
 
161
                        qDebug("root is not camera \n");
 
162
                }
 
163
        }else{
 
164
                qDebug()<< "errorMessage: " << errorMessage;
 
165
        }
 
166
}
 
167
 
 
168
void PhotoTexturer::removeCamera(int i){
 
169
        //checks if i is a valid index of the cameras list
 
170
        //and deletes the camera on position i
 
171
        if (i>=0 && i < cameras.size()){
 
172
                cameras.removeAt(i);
 
173
        }
 
174
}
 
175
 
 
176
void PhotoTexturer::storeOriginalTextureCoordinates(MeshModel *m){
 
177
        qDebug()<<"storeOriginalTextureCoordinates";
 
178
        // see http://vcg.sourceforge.net/index.php/Tutorial#User-defined_attributes
 
179
        //if (m->cm.HasPerWedgeTexCoord()){     //Problem HasPerWedgeTexCoord() returns true even if MeshModel
 
180
        //has no texture information
 
181
 
 
182
        //checks if the MeshModel has texture coordinates
 
183
        if(m->hasDataMask(MeshModel::MM_WEDGTEXCOORD) ){
 
184
                //qDebug()<<"HasPerWedgeTexCoord";
 
185
                CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> >ih;
 
186
                if (!vcg::tri::HasPerFaceAttribute(m->cm,UVTEXTURECOORDS)){
 
187
                        //qDebug()<<"has no PhotoTexturingUVCoords";
 
188
                        ih = vcg::tri::Allocator<CMeshO>::AddPerFaceAttribute<QMap<int,UVFaceTexture*> >(m->cm,UVTEXTURECOORDS);                
 
189
                }else{
 
190
                        ih = vcg::tri::Allocator<CMeshO>::AddPerFaceAttribute<QMap<int,UVFaceTexture*> >(m->cm,UVTEXTURECOORDS);
 
191
                }
 
192
                //checks if the original texture coordinates has been saved before
 
193
        
 
194
                if (origTextureID == -1){
 
195
                        //qDebug()<<"has no OriginalTextureCoords";
 
196
                        origTextureID = generateTextureId();
 
197
                        //CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> >ih = vcg::tri::Allocator<CMeshO>::AddPerFaceAttribute<QMap<int,UVFaceTexture*> >(m->cm,UVTEXTURECOORDS);
 
198
 
 
199
                        //saves the texture information for each face as perFaceAttribute
 
200
                        CMeshO::FaceIterator fi; int i = 0;
 
201
                        for(fi   = m->cm.face.begin(); fi != m->cm.face.end(); ++fi,i++){
 
202
                                UVFaceTexture* uvft = new UVFaceTexture();
 
203
                                uvft->u[0] = (*fi).WT(0).u();
 
204
                                uvft->v[0] = (*fi).WT(0).v();
 
205
 
 
206
                                uvft->u[1] = (*fi).WT(1).u();
 
207
                                uvft->v[1] = (*fi).WT(1).v();
 
208
 
 
209
                                uvft->u[2] = (*fi).WT(2).u();
 
210
                                uvft->v[2] = (*fi).WT(2).v();
 
211
 
 
212
                                uvft->textureindex = (*fi).WT(0).n();
 
213
                                uvft->faceIndex = i;
 
214
 
 
215
                                ih[i][origTextureID]  = uvft;   // [] operator takes a iterator
 
216
                        }
 
217
                        textureList[origTextureID]="original";
 
218
                }else{
 
219
                        //qDebug()<<"has OriginalTextureCoords";
 
220
                }
 
221
        }else{
 
222
                //qDebug()<<"!HasPerWedgeTexCoord";
 
223
        }
 
224
 
 
225
}
 
226
 
 
227
void PhotoTexturer::restoreOriginalTextureCoordinates(MeshModel *m){
 
228
        //qDebug() << "restoreOriginalTextureCoordinates";
 
229
        // see http://vcg.sourceforge.net/index.php/Tutorial#User-defined_attributes
 
230
 
 
231
        //checks if the original texture informationof the MeshModel were stored
 
232
        if (origTextureID!= -1 && vcg::tri::HasPerFaceAttribute(m->cm,UVTEXTURECOORDS)){
 
233
                applyTextureToMesh(m,origTextureID);
 
234
 
 
235
        }else{
 
236
                //qDebug()<<"has no OriginalTextureCoords";
 
237
        }
 
238
}
 
239
 
 
240
 
 
241
 
 
242
void PhotoTexturer::calculateMeshTextureForAllCameras(MeshModel *m, bool calcZBuffer){
 
243
        //checks if the MeshModel already has the perfaceAttribute PhotoTexturer::CAMERAUVTEXTURECOORDS
 
244
        //if not it creates one
 
245
 
 
246
 
 
247
        //enables texture information for the MeshModel
 
248
        //m->updateDataMask(MeshModel::MM_WEDGTEXCOORD);
 
249
        //makes sure that the mesh model mask enabels texture coordinates (needed to save the uv coorinates later)
 
250
        //m->ioMask |= MeshModel::IOM_WEDGTEXCOORD;
 
251
 
 
252
        
 
253
        //checks if special transformation data is stored asMeshData
 
254
 
 
255
        
 
256
        
 
257
        //calculates the texture information (uv coordinates and texture index) for each camera
 
258
        int i;
 
259
        for (i=0;i<cameras.size();i++){
 
260
                Camera *cam = cameras.at(i);
 
261
                calculateMeshTextureForCamera(m,cam, calcZBuffer);
 
262
        }
 
263
}
 
264
 
 
265
void PhotoTexturer::calculateMeshTextureForCamera(MeshModel *m, Camera* cam,bool calcZBuffer){
 
266
        bool found = false;
 
267
        unsigned int size = static_cast<unsigned int>(m->cm.textures.size());
 
268
        unsigned j = 0;
 
269
        int tindx;
 
270
 
 
271
        //gets the perFaceAttributeHandler for the perFaceAttribute PhotoTexturer::CAMERAUVTEXTURECOORDS
 
272
        CMeshO::PerFaceAttributeHandle<QMap<int ,UVFaceTexture*> > ih;
 
273
        
 
274
        if (!vcg::tri::HasPerFaceAttribute(m->cm,UVTEXTURECOORDS)){
 
275
                //qDebug()<<"has no PhotoTexturingUVCoords";
 
276
                ih = vcg::tri::Allocator<CMeshO>::AddPerFaceAttribute<QMap<int,UVFaceTexture*> > (m->cm,UVTEXTURECOORDS);
 
277
        }else{
 
278
                ih = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> > (m->cm,UVTEXTURECOORDS);
 
279
        }
 
280
        
 
281
        vcg::Matrix44f matrixTr = m->cm.Tr;
 
282
        vcg::Matrix44f matrix;
 
283
        vcg::Matrix44f matrixInv;
 
284
        if(vcg::tri::HasPerMeshAttribute(m->cm, PhotoTextureTools::TransformForPhoto)){
 
285
                CMeshO::PerMeshAttributeHandle<vcg::Matrix44f> transformHandle = vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<vcg::Matrix44f> (m->cm, PhotoTextureTools::TransformForPhoto);
 
286
                matrix = transformHandle();
 
287
                matrixInv =vcg::Inverse(matrix);
 
288
                m->cm.Tr = matrix;
 
289
                vcg::tri::UpdatePosition<CMeshO>::Matrix(m->cm, m->cm.Tr,true);
 
290
                //vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m->cm);
 
291
                vcg::tri::UpdateBounding<CMeshO>::Box(m->cm);
 
292
                
 
293
                qDebug()<< "transformHandle";
 
294
        }/*else{
 
295
                qDebug()<<"Identity";
 
296
                matrix = vcg::Matrix44f();
 
297
                matrix.SetIdentity();
 
298
        }
 
299
        
 
300
        
 
301
        m->cm.Tr = matrix;
 
302
        */
 
303
        //stdout << "matrix" << matrix;
 
304
        qDebug() << "matrix2: " << matrix[0][0]<< matrix[0][1]<< matrix[0][2]<< matrix[0][3]<< matrix[1][0]<< matrix[1][1]<< matrix[1][2]<< matrix[1][3]<< matrix[2][0]<< matrix[2][1]<< matrix[2][2]<< matrix[2][3]<< matrix[3][0]<< matrix[3][1]<< matrix[3][2]<< matrix[3][3];
 
305
        
 
306
        //loads the texture image and gets its dimensions
 
307
        QImage *img = new QImage(cam->textureImage);
 
308
        int imgw = img->width();
 
309
        int imgh = img->height();
 
310
 
 
311
        //looks if the texture image is allready loaded and stores the index of the texture
 
312
        //under tindx
 
313
        while (!found && (j < size))
 
314
        {
 
315
                if (cam->textureImage.toStdString().compare(m->cm.textures[j])==0)
 
316
                {
 
317
                        tindx = (int)j;
 
318
                        found = true;
 
319
                }
 
320
                ++j;
 
321
        }
 
322
 
 
323
        if (!found)
 
324
        {
 
325
                m->cm.textures.push_back(cam->textureImage.toStdString());
 
326
                tindx = (int)size;
 
327
        }
 
328
 
 
329
 
 
330
        //cam->calibration->calibrateToTsai(m);
 
331
        int textureId = generateTextureId();
 
332
        cam->textureId = textureId;
 
333
        QList<QuadTreeLeaf*> buildQuadTree;
 
334
        //calculates the uv coordinates for each face and saves them as UVFaceTexture as
 
335
        //perFaceAttribute of the MeshModel
 
336
        CMeshO::FaceIterator fi;
 
337
        int count = 0;
 
338
        for(fi=m->cm.face.begin(); fi!=m->cm.face.end(); ++fi, count++) {
 
339
                int i;
 
340
                UVFaceTexture *ft = new UVFaceTexture();
 
341
                ft->type = 0;
 
342
                //calculating angle between the camera direction and the face normal
 
343
                vcg::Matrix33f rMatrix = vcg::Matrix33f(matrix,3);
 
344
                //vcg::Point3f tmpN = rMatrix*(*fi).N();
 
345
                vcg::Point3f tmpN = (*fi).N();
 
346
                tmpN.Normalize();
 
347
                double angle = ((-1*cam->calibration->cameraDirection[0])*tmpN[0])
 
348
                                                +((-1*cam->calibration->cameraDirection[1])*tmpN[1])
 
349
                                                +((-1*cam->calibration->cameraDirection[2])*tmpN[2]);
 
350
                angle = acos(angle);
 
351
                angle = (angle/M_PI)*180.0;
 
352
 
 
353
                //qDebug()<< "angle: " << angle;
 
354
                ft->faceAngleToCamera = angle;
 
355
 
 
356
                for (i=0;i<3;i++){
 
357
 
 
358
                        double u,v;
 
359
                        //vcg::Point3f tmpVector = matrix*(*fi).V(i)->cP();
 
360
                        vcg::Point3f tmpVector = (*fi).V(i)->cP();
 
361
                        cam->calibration->getUVforPoint(tmpVector[0],tmpVector[1],tmpVector[2],&u,&v);
 
362
 
 
363
                        ft->u[i] = u/cam->resolution[0];
 
364
                        ft->v[i] = 1.0-v/cam->resolution[1];
 
365
 
 
366
                }
 
367
                ft->textureindex =tindx;
 
368
                ft->faceIndex = count;
 
369
 
 
370
                ih[ft->faceIndex][textureId] = ft;
 
371
                buildQuadTree.push_back(ft);
 
372
 
 
373
        }
 
374
        
 
375
        if (cam->zBuffer!= NULL){
 
376
                delete cam->zBuffer;
 
377
                cam->zBuffer = NULL;
 
378
        }
 
379
        if(calcZBuffer){
 
380
                QuadTreeNode zBufferTree = QuadTreeNode(0.0,0.0,1.0,1.0);
 
381
                zBufferTree.buildQuadTree(&buildQuadTree,1.0/imgw,1.0/imgh);
 
382
                cam->zBuffer = new TextureFilterZB(imgw,imgh,1);
 
383
                calculateZBuffer(m,cam,&zBufferTree,cam->zBuffer);
 
384
                cam->zBuffer->normalize();
 
385
        }
 
386
        //save Z-Buffer as image
 
387
        //cam->zBuffer->SaveAsImage("zbuffer_",cam->name);
 
388
        cam->calculatedTextures = true;
 
389
        textureList[textureId]= cam->name;
 
390
        
 
391
        
 
392
        if(vcg::tri::HasPerMeshAttribute(m->cm, PhotoTextureTools::TransformForPhoto)){
 
393
                        m->cm.Tr = matrixInv;
 
394
                        vcg::tri::UpdatePosition<CMeshO>::Matrix(m->cm, m->cm.Tr);
 
395
                        //vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m->cm);
 
396
                        vcg::tri::UpdateBounding<CMeshO>::Box(m->cm);
 
397
                        m->cm.Tr = matrixTr;
 
398
                        qDebug()<< "transformHandle";
 
399
        }
 
400
}
 
401
 
 
402
void PhotoTexturer::applyTextureToMesh(MeshModel *m,int textureIdx, bool use_different_tidx, int tidx){
 
403
        
 
404
        if(!m->hasDataMask(MeshModel::MM_WEDGTEXCOORD)){
 
405
                m->updateDataMask(MeshModel::MM_WEDGTEXCOORD);
 
406
        }
 
407
        QMap<int, QString>::const_iterator i = textureList.find(textureIdx);
 
408
         if (i != textureList.end()){
 
409
        
 
410
                if (vcg::tri::HasPerFaceAttribute(m->cm,UVTEXTURECOORDS)){
 
411
        
 
412
                        CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> > ih = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> > (m->cm,UVTEXTURECOORDS);
 
413
                        CMeshO::FaceIterator fi;
 
414
                        int k =0;
 
415
                        for(fi=m->cm.face.begin(); fi!=m->cm.face.end(); ++fi) {
 
416
                                int i;
 
417
                                UVFaceTexture* ft = ih[fi][textureIdx];
 
418
                                if(ft!=NULL){
 
419
                                        for (i=0;i<3;i++){
 
420
                                                (*fi).WT(i).u() = ft->u[i];
 
421
                                                (*fi).WT(i).v() = ft->v[i];
 
422
                                                if (use_different_tidx && tidx >-1){
 
423
                                                        (*fi).WT(i).n() = tidx;
 
424
                                                }else{
 
425
                                                        (*fi).WT(i).n() = ft->textureindex;
 
426
                                                }
 
427
                                        }
 
428
                                }
 
429
                                k++;
 
430
                        }
 
431
                        //m->cm
 
432
                }
 
433
        }
 
434
}
 
435
 
 
436
 
 
437
void PhotoTexturer::unprojectToOriginalTextureMap(MeshModel *m, Camera* camera, QuadTreeNode &qtree, ImageFilterContainer *container ,bool use_distance_filter, int distance_weight, bool use_angle_filter, int angle_weight , int angle_map_sharpness, double min_angle, int imgResX, int imgResY){
 
438
        qDebug() <<"unprojectToOriginalTextureMap"<< min_angle;
 
439
 
 
440
        //checks if the MeshModel has original uv coordinates and camera projected uv coordinates.
 
441
        if (origTextureID != -1 && vcg::tri::HasPerFaceAttribute(m->cm,UVTEXTURECOORDS)){
 
442
 
 
443
                //CMeshO::PerFaceAttributeHandle<UVFaceTexture*> oth = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<UVFaceTexture*>(m->cm,ORIGINALUVTEXTURECOORDS);
 
444
                CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> > cth = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> > (m->cm,UVTEXTURECOORDS);
 
445
                
 
446
                
 
447
                
 
448
                vcg::Matrix44f matrixTr = m->cm.Tr;
 
449
                vcg::Matrix44f matrix;
 
450
                vcg::Matrix44f matrixInv;
 
451
                if(vcg::tri::HasPerMeshAttribute(m->cm, PhotoTextureTools::TransformForPhoto)){
 
452
                        CMeshO::PerMeshAttributeHandle<vcg::Matrix44f> transformHandle = vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<vcg::Matrix44f> (m->cm, PhotoTextureTools::TransformForPhoto);
 
453
                        matrix = transformHandle();
 
454
                        matrixInv =vcg::Inverse(matrix);
 
455
                        m->cm.Tr = matrix;
 
456
                        vcg::tri::UpdatePosition<CMeshO>::Matrix(m->cm, m->cm.Tr,true);
 
457
                        //vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m->cm);
 
458
                        vcg::tri::UpdateBounding<CMeshO>::Box(m->cm);
 
459
                        
 
460
                        qDebug()<< "transformHandle";
 
461
                }
 
462
                
 
463
                QString camname = camera->name;
 
464
 
 
465
                //creates a new RGBA image for saving the new texture
 
466
                //QImage image(res_x, res_y, QImage::Format_ARGB32);
 
467
 
 
468
                container->image = new QImage(imgResX,imgResY,QImage::Format_ARGB32);
 
469
                TextureFilterSTD *distance_filter = NULL;
 
470
                TextureFilterSTD *angle_filter = NULL;
 
471
 
 
472
                if(use_angle_filter){
 
473
                        angle_filter = new TextureFilterSTD(imgResX,imgResY,angle_weight);
 
474
                }
 
475
                if (use_distance_filter){
 
476
                        distance_filter = new TextureFilterSTD(imgResX,imgResY,distance_weight);
 
477
                }
 
478
 
 
479
                //loading the texture corresponding to the camera
 
480
                QImage tmp_texture(camera->textureImage);
 
481
                QRgb* utimg = (QRgb*)tmp_texture.bits();
 
482
                int twidth = tmp_texture.width();
 
483
                int theight = tmp_texture.height();
 
484
                
 
485
                QColor cpixel;
 
486
 
 
487
                int x;
 
488
                int y;
 
489
                //CMeshO::FaceIterator fi;
 
490
                bool found = false;
 
491
 
 
492
                
 
493
                //goes pixelwise over the whole new texture image and looks if it lies inside
 
494
                //a texture face of the original texture coordinates. If the pixel lies inside
 
495
                //a textured face it looks in the corresponding camera texture for the color value
 
496
                //of this pixel and stores it at the current pixel position in the new texture image.
 
497
 
 
498
                QRgb* ucimg = (QRgb*)container->image->bits();
 
499
                
 
500
                for (y=0;y<imgResY;y++){
 
501
                        for (x=0;x<imgResX;x++){
 
502
 
 
503
                                //sets the current pixel to black with an alpha value of 0
 
504
                                cpixel = QColor(0, 0, 0, 0);
 
505
                                //container->image->setPixel(x,imgResY-(y+1), cpixel.rgba());
 
506
                                ucimg[(imgResY-(y+1))*imgResX+x] =  cpixel.rgba();
 
507
                                found = false;
 
508
                                //searches the QuadTree for matching faces
 
509
                                QList<QuadTreeLeaf*> list;
 
510
                                qtree.getLeafs(((double)x/(double)(imgResX-1)),((double)y/(double)(imgResY-1)),list);
 
511
                                int ns = list.size();
 
512
 
 
513
                                if (ns>0){
 
514
                                        int idx = 0;
 
515
                                        while(!found && idx <ns){
 
516
                                                UVFaceTexture* tmp;
 
517
                                                tmp = dynamic_cast<UVFaceTexture*>(list.at(idx));
 
518
 
 
519
                                                double u,v;
 
520
                                                double a,b,c,d;
 
521
                                                
 
522
                                                UVFaceTexture* ct = cth[tmp->faceIndex][camera->textureId];
 
523
                                                tmp->getBarycentricCoordsForUV(((double)x/(double)(imgResX-1)),((double)y/(double)(imgResY-1)),a,b,c,d);
 
524
                                                
 
525
                                                ct->getUVatBarycentricCoords(u,v,a,b,c);
 
526
                                                int ix = (int)(((double)twidth-1)*u);
 
527
                                                int iy = theight-(int)((((double)theight-1)*v)+1);
 
528
 
 
529
                                                if(ix>=0 && ix<twidth && iy>=0 && iy<theight){
 
530
 
 
531
 
 
532
                                                        //calculating alpha value of the pixel by using the angle
 
533
 
 
534
                                                        CFaceO f;
 
535
                                                        f = m->cm.face.at(tmp->faceIndex);
 
536
                                                        
 
537
                                                        vcg::Point3f p;
 
538
                                                        p =  f.V(0)->cP()*a+ f.V(1)->cP()*b+f.V(2)->cP()*c;
 
539
                                                        double distance = sqrt(pow(p[0]-camera->calibration->cameraPosition[0],2)+pow(p[1]-camera->calibration->cameraPosition[1],2)+pow(p[2]-camera->calibration->cameraPosition[2],2));
 
540
 
 
541
                                                        if((camera->zBuffer!= 0 && (camera->zBuffer->normalizeValue(distance)-ZB_EPSILON)<=camera->zBuffer->getValue(ix,tmp_texture.height()-(iy+1)))|| (camera->zBuffer== 0 )){
 
542
                                                                
 
543
                                                                found = true;
 
544
                                                                
 
545
                                                                //cpixel = QColor(tmp_texture.pixel(ix,iy));
 
546
                                                                cpixel = QColor(utimg[iy*twidth+ix]);
 
547
                                                                cpixel.setAlpha(255);
 
548
                                                                //container->image->setPixel(x,imgResY-(y+1), cpixel.rgba());
 
549
                                                                ucimg[(imgResY-(y+1))*imgResX+x] = cpixel.rgba();
 
550
        
 
551
                                                                double angle = 0.0;
 
552
                                                                if(use_angle_filter){
 
553
                                                                        //calculate normal vector for pixel
 
554
                                                                        double n1, n2,n3;
 
555
                                                                        n1 = a*f.V(0)->N()[0]+ b*f.V(1)->N()[0]+c*f.V(2)->N()[0];
 
556
                                                                        n2 = a*f.V(0)->N()[1]+ b*f.V(1)->N()[1]+c*f.V(2)->N()[1];
 
557
                                                                        n3 = a*f.V(0)->N()[2]+ b*f.V(1)->N()[2]+c*f.V(2)->N()[2];
 
558
        
 
559
                                                                        angle = ((-1*camera->calibration->cameraDirection[0])*n1)
 
560
                                                                                                        +((-1*camera->calibration->cameraDirection[1])*n2)
 
561
                                                                                                        +((-1*camera->calibration->cameraDirection[2])*n3);
 
562
        
 
563
                                                                        //qDebug() << "angle["<<ix<<"]["<<iy<<"]: " <<angle;
 
564
        
 
565
        
 
566
                                                                        angle = acos(angle);
 
567
                                                                        angle = (angle/M_PI)*180.0;
 
568
        
 
569
                                                                        if(angle<= min_angle){
 
570
                                                                                double wangle = (angle/180.0)*M_PI;
 
571
                                                                                wangle = sin(wangle);
 
572
                                                                                wangle = pow(wangle,angle_map_sharpness);
 
573
        
 
574
                                                                                angle_filter->setValue(x,imgResY-(y+1),wangle);
 
575
                                                                        }
 
576
                                                                }
 
577
        
 
578
                                                                if(use_distance_filter){
 
579
                                                                        //calculate distance for pixel
 
580
                                                                        distance_filter->setValue(x,imgResY-(y+1),distance);
 
581
                                                                }
 
582
                                                                        
 
583
                                                                
 
584
                                                                if (angle<= min_angle){
 
585
                                                                        //cpixel = QColor(tmp_texture.pixel(ix,iy));
 
586
                                                                        cpixel = QColor(utimg[iy*twidth+ix]);
 
587
                                                                        //int rgb = (int)((angle/90.0*255.0));
 
588
                                                                        //cpixel = QColor(rgb,rgb,rgb);
 
589
                                                                        cpixel.setAlpha((int)((angle/90.0*255.0)));
 
590
                                                                        //cpixel.setAlpha(255);
 
591
        
 
592
                                                                }else{
 
593
                                                                        cpixel = QColor(0,0,0,0);
 
594
 
 
595
                                                                }
 
596
                                                                //container->image->setPixel(x,imgResY-(y+1), cpixel.rgba());
 
597
                                                                ucimg[(imgResY-(y+1))*imgResX+x] = cpixel.rgba();
 
598
                                                        }
 
599
                                                }else{
 
600
 
 
601
 
 
602
                                                }
 
603
                                                //}
 
604
                                                idx++;
 
605
                                        }if(!found){
 
606
                                                //qDebug() << "not found ";
 
607
                                        }
 
608
 
 
609
                                }
 
610
                        }
 
611
                }
 
612
                if(use_angle_filter){
 
613
                        container->addFilter(angle_filter);
 
614
                }
 
615
                if(use_distance_filter){
 
616
                        container->addFilter(distance_filter);
 
617
                }
 
618
                
 
619
                
 
620
                if(vcg::tri::HasPerMeshAttribute(m->cm, PhotoTextureTools::TransformForPhoto)){
 
621
                                m->cm.Tr = matrixInv;
 
622
                                vcg::tri::UpdatePosition<CMeshO>::Matrix(m->cm, m->cm.Tr);
 
623
                                //vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m->cm);
 
624
                                vcg::tri::UpdateBounding<CMeshO>::Box(m->cm);
 
625
                                m->cm.Tr = matrixTr;
 
626
                                qDebug()<< "transformHandle";
 
627
                }
 
628
        }
 
629
}
 
630
void PhotoTexturer::getSurrundingMeanColor(QRgb* uimg, int iwidth, int iheight, int x, int y, QColor &surcolor){
 
631
        //qDebug()<<"getSurrundingMeanColor: "<<x<<y;
 
632
        
 
633
        if((x>=0) && (x< iwidth) && (y>=0) && (y< iheight)){
 
634
                QColor c[8];
 
635
                c[0] = QColor(0,0,0,0);
 
636
                c[1] = QColor(0,0,0,0);
 
637
                c[2] = QColor(0,0,0,0);
 
638
                c[3] = QColor(0,0,0,0);
 
639
                c[4] = QColor(0,0,0,0);
 
640
                c[5] = QColor(0,0,0,0);
 
641
                c[6] = QColor(0,0,0,0);
 
642
                c[7] = QColor(0,0,0,0);
 
643
                if((x-1>=0) && (x-1< iwidth) && (y-1>=0) && (y-1< iheight)){
 
644
                        //c[0]=QColor::fromRgba(image.pixel(x-1,y-1));
 
645
                        c[0]=QColor::fromRgba(uimg[(y-1)*iwidth+(x-1)]);
 
646
                }
 
647
 
 
648
                if((x>=0) && (x< iwidth) && (y-1>=0) && (y-1< iheight)){
 
649
                        //c[1]=QColor::fromRgba(image.pixel(x,y-1));
 
650
                        c[1]=QColor::fromRgba(uimg[(y-1)*iwidth+(x)]);
 
651
                }
 
652
                if((x+1>=0) && (x+1< iwidth) && (y-1>=0) && (y-1< iheight)){
 
653
                        //c[2]=QColor::fromRgba(image.pixel(x+1,y-1));
 
654
                        c[2]=QColor::fromRgba(uimg[(y-1)*iwidth+(x+1)]);
 
655
                }
 
656
                if((x+1>=0) && (x+1< iwidth) && (y>=0) && (y< iheight)){
 
657
                        //c[3]=QColor::fromRgba(image.pixel(x+1,y));
 
658
                        c[3]=QColor::fromRgba(uimg[(y)*iwidth+(x+1)]);
 
659
                }
 
660
                if((x+1>=0) && (x+1< iwidth) && (y+1>=0) && (y+1< iheight)){
 
661
                        //c[4]=QColor::fromRgba(image.pixel(x+1,y+1));
 
662
                        c[4]=QColor::fromRgba(uimg[(y+1)*iwidth+(x+1)]);
 
663
                }
 
664
                if((x>=0) && (x< iwidth) && (y+1>=0) && (y+1< iheight)){
 
665
                        //c[5]=QColor::fromRgba(image.pixel(x,y+1));
 
666
                        c[5]=QColor::fromRgba(uimg[(y+1)*iwidth+(x)]);
 
667
                }
 
668
                if((x-1>=0) && (x-1< iwidth) && (y+1>=0) && (y+1< iheight)){
 
669
                        //c[6]=QColor::fromRgba(image.pixel(x-1,y+1));
 
670
                        c[6]=QColor::fromRgba(uimg[(y+1)*iwidth+(x-1)]);
 
671
                }
 
672
                if((x-1>=0) && (x-1< iwidth) && (y>=0) && (y< iheight)){
 
673
                        //c[7]=QColor::fromRgba(image.pixel(x-1,y));
 
674
                        c[7]=QColor::fromRgba(uimg[(y)*iwidth+(x-1)]);
 
675
                }
 
676
                int i;
 
677
                int r=0;
 
678
                int g=0;
 
679
                int b=0;
 
680
                int a=0;
 
681
                int count=0;
 
682
                for(i=0;i<8;i++){
 
683
                        if(c[i].alpha()>0){
 
684
                                r+=c[i].red();
 
685
                                g+=c[i].green();
 
686
                                b+=c[i].blue();
 
687
                                a+= c[i].alpha();
 
688
                                count++;
 
689
                        }
 
690
                }
 
691
                if(count>0){
 
692
                        surcolor.setRed(r/count);
 
693
                        surcolor.setGreen(g/count);
 
694
                        surcolor.setBlue(b/count);
 
695
                        surcolor.setAlpha(a/count);
 
696
                        surcolor.setAlpha(255);
 
697
                }else{
 
698
                        surcolor.setRed(0);
 
699
                        surcolor.setGreen(0);
 
700
                        surcolor.setBlue(0);
 
701
                        surcolor.setAlpha(0);
 
702
                }
 
703
 
 
704
        }
 
705
 
 
706
 
 
707
}
 
708
 
 
709
 
 
710
void PhotoTexturer::edgeTextureStretching(QImage *image, int pass){
 
711
        QRgb* uimg = (QRgb*) image->bits();
 
712
        int width = image->width();
 
713
        int height = image->height();
 
714
        if(pass>0){
 
715
                int count = 0;
 
716
                while(pass>0){
 
717
                        //qDebug()<< "edgeTextureStretching pass:" <<++count;
 
718
                        QImage tmp_image = image->copy(0,0,width,height);
 
719
                        QRgb* utimg = (QRgb*) tmp_image.bits();
 
720
                        int x;
 
721
                        int y;
 
722
                        for(y=0;y<height;y++){
 
723
                                for(x=0;x<width;x++){
 
724
                                        //QColor test = QColor::fromRgba(image->pixel(x,y));
 
725
                                        QColor test = QColor::fromRgba(uimg[y*width+x]);
 
726
                                        if(test.alpha()==0){
 
727
                                                //qDebug()<< "alpha == 0";
 
728
                                                QColor surcolor;
 
729
                                                getSurrundingMeanColor(utimg,width,height,x,y,surcolor);
 
730
                                                //image->setPixel(x,y,surcolor.rgba());
 
731
                                                uimg[y*width+x] = surcolor.rgba();
 
732
                                        }
 
733
                                }
 
734
                        }
 
735
 
 
736
 
 
737
                        pass--;
 
738
                }
 
739
        }
 
740
}
 
741
 
 
742
 
 
743
int PhotoTexturer::unprojectTextures(MeshModel *m, int textureID, FilterParameterSet *paraSet){
 
744
        int width = paraSet->getInt(TEXTURE_SIZE_WIDTH);
 
745
        int height = paraSet->getInt(TEXTURE_SIZE_HEIGHT);
 
746
        int ets = paraSet->getInt(UNPROJECT_EDGE_STRETCHING_PASS);
 
747
        //bool enable_angle_map = paraSet->getBool(UNPROJECT_ENABLE_ANGLE);
 
748
        //int angle_weight = paraSet->getInt(UNPROJECT_ANGLE_WEIGHT);
 
749
        //int angle_map_sharpness = paraSet->getInt(UNPROJECT_ANGLE_SHARPNESS);
 
750
        //double min_angle = paraSet->getFloat(UNPROJECT_ANGLE);
 
751
        //bool enable_distance_map = paraSet->getBool(UNPROJECT_ENABLE_DISTANCE);
 
752
        //int distance_weight = paraSet->getInt(UNPROJECT_DISTANCE_WEIGHT);
 
753
        QString smartblend = paraSet->getString(BAKE_SMARTBLEND);
 
754
        
 
755
        QList<QuadTreeLeaf*> *list = new QList<QuadTreeLeaf*>();
 
756
        CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> >oth = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> >(m->cm,UVTEXTURECOORDS);
 
757
        CMeshO::FaceIterator fi;
 
758
        for(fi = m->cm.face.begin();fi!=m->cm.face.end();fi++) {
 
759
                list->push_back(oth[fi][origTextureID]);
 
760
        }
 
761
 
 
762
        QuadTreeNode qtree = QuadTreeNode(0.0,0.0,1.0,1.0);
 
763
        //qDebug() << "list->size(): "<<list->size();
 
764
        //qDebug()<< "buildQuadTree";
 
765
        qtree.buildQuadTree(list, 0.50/(double)width,0.50/(double)height);
 
766
/*
 
767
        ImageFilterContainer *ifc = new ImageFilterContainer();
 
768
        unprojectToOriginalTextureMap(m,camera,qtree,ifc, enable_distance_map, distance_weight, enable_angle_map,angle_weight,angle_map_sharpness,min_angle,width,height);
 
769
                
 
770
        ifc->image->save(unprojectTextureName,"PNG");
 
771
*/      
 
772
        return 0;
 
773
        //delete image;
 
774
}
 
775
 
 
776
int PhotoTexturer::bakeTextures(MeshModel *m, FilterParameterSet *paraSet){
 
777
        int width = paraSet->getInt(TEXTURE_SIZE_WIDTH);
 
778
        int height = paraSet->getInt(TEXTURE_SIZE_HEIGHT);
 
779
        bool enable_ets = paraSet->getBool(UNPROJECT_ENABLE_EDGE_STRETCHING);
 
780
        int ets = paraSet->getInt(UNPROJECT_EDGE_STRETCHING_PASS);
 
781
        bool enable_angle_map = paraSet->getBool(UNPROJECT_ENABLE_ANGLE);
 
782
        int angle_weight = paraSet->getInt(UNPROJECT_ANGLE_WEIGHT);
 
783
        int angle_map_sharpness = paraSet->getInt(UNPROJECT_ANGLE_SHARPNESS);
 
784
        double min_angle = paraSet->getFloat(UNPROJECT_ANGLE);
 
785
        bool enable_distance_map = paraSet->getBool(UNPROJECT_ENABLE_DISTANCE);
 
786
        int distance_weight = paraSet->getInt(UNPROJECT_DISTANCE_WEIGHT);
 
787
        QString smartblend = paraSet->getString(BAKE_SMARTBLEND);
 
788
        int merger_type = paraSet->getEnum(BAKE_MERGE_TYPE);
 
789
        bool saveUnprojected = paraSet->getBool(BAKE_SAVE_UNPROJECT);
 
790
        //creating a list of all UVFaceTexture
 
791
        QList<QuadTreeLeaf*> list;
 
792
        CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> >oth = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> >(m->cm,UVTEXTURECOORDS);
 
793
        CMeshO::FaceIterator fi;
 
794
        for(fi = m->cm.face.begin();fi!=m->cm.face.end();fi++) {
 
795
                list.push_back(oth[fi][origTextureID]);
 
796
        }
 
797
 
 
798
        //creating a quadtree from list UVFaceTexture
 
799
        QuadTreeNode qtree = QuadTreeNode(0.0,0.0,1.0,1.0);
 
800
        qtree.buildQuadTree(&list, 0.50/(double)width,0.50/(double)height);
 
801
        TextureMerger *texMerger = NULL;
 
802
        //deciedes which TextureMerger to use
 
803
        if (merger_type == 0){
 
804
                texMerger = new WinnerTakesAllTextureMerger();
 
805
        }else if(merger_type == 1){
 
806
                texMerger = new SmartBlendTextureMerger(smartblend);
 
807
        }
 
808
        if (texMerger != NULL){
 
809
                for (int i=0;i<cameras.size();i++){
 
810
                        Camera *camera = cameras.at(i);
 
811
                        if(camera->textureId >-1){
 
812
                                ImageFilterContainer *ifc = new ImageFilterContainer();
 
813
                                ifc->tag = camera->name;
 
814
                                unprojectToOriginalTextureMap(m,camera,qtree,ifc, enable_distance_map, distance_weight, enable_angle_map,angle_weight,angle_map_sharpness,min_angle,width,height);
 
815
                                texMerger->ifcList.push_back(ifc);
 
816
                        }
 
817
                }
 
818
                texMerger->normalizeFilterContainerList();
 
819
                
 
820
                if (saveUnprojected){
 
821
                        ImageFilterContainer *ifc;
 
822
                        QFileInfo fi = QFileInfo(m->fileName.c_str());
 
823
                        for (int i=0;i<texMerger->ifcList.size();i++){
 
824
                                ifc = texMerger->ifcList.at(i);
 
825
                                QString upTextureName = fi.baseName()+"_unproject_"+ifc->tag+".png";
 
826
                                ifc->image->save(upTextureName,"PNG");
 
827
                        }
 
828
                }
 
829
                
 
830
                QImage *image = texMerger->merge(width,height);
 
831
                if(image !=NULL){
 
832
                        bakeCounter++;
 
833
                        
 
834
                        if(enable_ets){
 
835
                                edgeTextureStretching(image,ets);
 
836
                        }
 
837
                        QString filename = paraSet->getString(BAKE_MERGED_TEXTURE);
 
838
                        
 
839
                        QImage final_image = image->convertToFormat(QImage::Format_RGB32);
 
840
 
 
841
                        final_image.save(filename,"PNG");
 
842
                        
 
843
                        //create new UVTexture set
 
844
                        qDebug()<<"filename:"<<filename;
 
845
                        int textureId = generateTextureId();
 
846
                        bool found = false;
 
847
                        unsigned int size = static_cast<unsigned int>(m->cm.textures.size());
 
848
                        unsigned j = 0;
 
849
                        int tindx;
 
850
                        while (!found && (j < size)){
 
851
                                
 
852
                                if (filename.toStdString().compare(m->cm.textures[j])==0)
 
853
                                {
 
854
                                        tindx = (int)j;
 
855
                                        found = true;
 
856
                                }
 
857
                                ++j;
 
858
                        }
 
859
                
 
860
                        if (!found)
 
861
                        {
 
862
                                m->cm.textures.push_back(filename.toStdString());
 
863
                                tindx = (int)size;
 
864
                        }
 
865
                        
 
866
                        qDebug()<<"tindx:"<<tindx;
 
867
                        
 
868
                        if (origTextureID>-1){
 
869
                                        qDebug()<<"has OriginalTextureCoords";
 
870
                                        //CMeshO::PerFaceAttributeHandle<UVFaceTexture*> ihot = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<UVFaceTexture*> (m->cm,ORIGINALUVTEXTURECOORDS);
 
871
                                        CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> > cth = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> > (m->cm,UVTEXTURECOORDS);
 
872
                
 
873
                                        //overwrites the current texture information with the original texture information
 
874
                                        // from the perFaceAttribute "ORIGINALUVTEXTURECOORDS"
 
875
                                        CMeshO::FaceIterator fi; int i = 0;
 
876
                                        for(fi   = m->cm.face.begin(); fi != m->cm.face.end(); ++fi,++i){
 
877
                                                
 
878
                                                UVFaceTexture* uvft = cth[fi][origTextureID] ;
 
879
                                                UVFaceTexture* tmp = new UVFaceTexture(*uvft);
 
880
                                                tmp->textureindex = tindx;
 
881
                                                tmp->type = 1;
 
882
                                                cth[fi][textureId] = tmp;
 
883
                
 
884
                
 
885
                                        }
 
886
                                }else{
 
887
                                        //qDebug()<<"has no OriginalTextureCoords";
 
888
                                }
 
889
                        qDebug()<<"textureId:"<<textureId;
 
890
                        if(merger_type==0){
 
891
                                textureList[textureId]="baked_win_"+QString::number(bakeCounter);
 
892
                        }else if(merger_type==1){
 
893
                                textureList[textureId]="baked_sb_"+QString::number(bakeCounter);
 
894
                        }
 
895
                        
 
896
                        delete texMerger;
 
897
                        return textureId;
 
898
                        delete image;
 
899
                        
 
900
                }
 
901
        }
 
902
        return 0;
 
903
}
 
904
 
 
905
 
 
906
QImage PhotoTexturer::mergeTextureImagesWinnerTakesAll(int imgWidth, int imgHeight, QList<QImage> imgList){
 
907
        QImage image = QImage(imgWidth,imgHeight,QImage::Format_RGB32);
 
908
        int x;
 
909
        int y;
 
910
        for(x=0; x<imgWidth;x++){
 
911
                for(y=0;y<imgHeight;y++){
 
912
                        QColor cpixel = QColor(0, 0, 0, 0);
 
913
                        int i;
 
914
                        for(i=0;i<imgList.size();i++){
 
915
                                QImage tmpImg = imgList.at(i);
 
916
                                QColor tmpPixel = QColor::fromRgba(tmpImg.pixel(x,y));
 
917
                                if(cpixel.alpha()<tmpPixel.alpha()){
 
918
                                        cpixel = QColor(tmpPixel);
 
919
                                }
 
920
                        }
 
921
                        image.setPixel(x,y,cpixel.rgba());
 
922
 
 
923
                }
 
924
        }
 
925
        return image;
 
926
}
 
927
 
 
928
void PhotoTexturer::convertToTsaiCamera(int camIdx, bool optimize, QString filename,MeshModel *mm){
 
929
        if(camIdx>=0 && camIdx< cameras.size()){
 
930
                Camera* newCam = new Camera();
 
931
                Camera* oldCam = cameras.at(camIdx);
 
932
 
 
933
                newCam->name = oldCam->name;
 
934
                newCam->resolution[0] = oldCam->resolution[0];
 
935
                newCam->resolution[1] = oldCam->resolution[1];
 
936
                newCam->textureImage = oldCam->textureImage;
 
937
                newCam->calibration = oldCam->calibration->calibrateToTsai(mm,optimize);
 
938
 
 
939
                QDomDocument doc(Camera::XML_CAMERADOCUMENT);
 
940
                QDomElement root = doc.createElement(Camera::XML_CAMERADOCUMENT);
 
941
                newCam->saveAsXml(&doc,&root);
 
942
                doc.appendChild(root);
 
943
                QFile file(filename);
 
944
                file.open(QIODevice::WriteOnly);
 
945
                QTextStream qstream(&file);
 
946
                doc.save(qstream,1);
 
947
                file.close();
 
948
 
 
949
        }
 
950
}
 
951
 
 
952
void PhotoTexturer::exportMaxScript(QString filename,MeshModel *mm){
 
953
 
 
954
        QFile* ms = new QFile(filename);
 
955
        if (ms->open(QIODevice::WriteOnly)){
 
956
             QTextStream out(ms);
 
957
             out << "(\n";
 
958
             int i;
 
959
             for (i=0;i<cameras.size();i++){
 
960
                 Camera* cam = cameras.at(i);
 
961
                 //TsaiCameraCalibration* tsai = dynamic_cast<TsaiCameraCalibration*>(cam->calibration);
 
962
                 TsaiCameraCalibration* tsai = dynamic_cast<TsaiCameraCalibration*>(cam->calibration->calibrateToTsai(mm,false));
 
963
                 if (tsai!=NULL){
 
964
                         out << "-- kappa1: "<< tsai->calib_const.kappa1<<"\n";
 
965
                         out << "-- Cx: "<< tsai->cam_para.Cx << "\tCy: "<<tsai->cam_para.Cy<<"\n";
 
966
                         out << "-- sx: "<< tsai->cam_para.sx<<"\n";
 
967
                         out << "-- p1: "<< tsai->calib_const.p1 << "\tp2: "<<tsai->calib_const.p2<<"\n";
 
968
                         out << "\n";
 
969
                         out << "r1 = [" << tsai->calib_const.r1<<",\t"<< -tsai->calib_const.r4<<",\t"<<-tsai->calib_const.r7<<"]\n";
 
970
                         out << "r2 = [" << tsai->calib_const.r2<<",\t"<< -tsai->calib_const.r5<<",\t"<<-tsai->calib_const.r8<<"]\n";
 
971
                         out << "r3 = [" << tsai->calib_const.r3<<",\t"<< -tsai->calib_const.r6<<",\t"<<-tsai->calib_const.r9<<"]\n";
 
972
                         out << "r4 = [" << tsai->calib_const.Tx<<",\t"<< -tsai->calib_const.Ty<<",\t"<<-tsai->calib_const.Tz<<"]\n";
 
973
 
 
974
                         out<< "m = matrix3 r1 r2 r3 r4\n";
 
975
 
 
976
                         out << "setRendApertureWidth ("<< tsai->cam_para.dpx * cam->resolution[0]<<")\n";//  -- horizontal size of sensor/filmback
 
977
                         out << "renderPixelAspect = " << tsai->cam_para.dpx/tsai->cam_para.dpy<<"\n"; //     -- non-square pixels?
 
978
                         out << "renderWidth = "<< cam->resolution[0] <<"\n";
 
979
                         out << "renderHeight = "<< cam->resolution[1] <<"\n";
 
980
 
 
981
                         out << "freecamera name:\""<< cam->name <<"\" fov:(cameraFOV.MMtoFOV "<<tsai->calib_const.f<<") transform:(inverse m)\n";
 
982
                         out << "\n\n";
 
983
                 }
 
984
             }
 
985
             out << ")\n";
 
986
             ms->close();
 
987
        }else{
 
988
                qDebug()<< "Could not open max script file." <<filename;
 
989
        }
 
990
 
 
991
 
 
992
}
 
993
 
 
994
 
 
995
 
 
996
int PhotoTexturer::combineTextures(MeshModel* m){
 
997
        int textureId  = -1;
 
998
        if (vcg::tri::HasPerFaceAttribute(m->cm,UVTEXTURECOORDS)){
 
999
                
 
1000
                CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> > ih = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> > (m->cm,UVTEXTURECOORDS);
 
1001
                CMeshO::FaceIterator fi;
 
1002
                textureId = generateTextureId();
 
1003
                
 
1004
                int k =0;
 
1005
                for(fi=m->cm.face.begin(); fi!=m->cm.face.end(); ++fi) {
 
1006
                        UVFaceTexture* ft =0;
 
1007
                        int j;
 
1008
                        for(j=0;j<cameras.size();j++){
 
1009
                                UVFaceTexture* tmp = ih[fi][cameras.at(j)->textureId];
 
1010
                                if (tmp!=NULL){
 
1011
                                        if(tmp->type == 0){
 
1012
                                                if (ft==0 || ft->faceAngleToCamera>tmp->faceAngleToCamera){
 
1013
                                                        
 
1014
                                                        if(((tmp->u[0]>=0.0 && tmp->u[0] <=1.0)&&(tmp->v[0]>=0.0 && tmp->v[0] <=1.0))&&
 
1015
                                                                ((tmp->u[1]>=0.0 && tmp->u[1] <=1.0)&&(tmp->v[1]>=0.0 && tmp->v[1] <=1.0))&&
 
1016
                                                                ((tmp->u[2]>=0.0 && tmp->u[2] <=1.0)&&(tmp->v[2]>=0.0 && tmp->v[2] <=1.0))){
 
1017
                                                                ft = tmp;
 
1018
                                                        }
 
1019
                                                }
 
1020
                                        }
 
1021
                                }
 
1022
                        }
 
1023
                        
 
1024
                        UVFaceTexture* tmp2 = NULL;
 
1025
                        if(ft!=NULL){
 
1026
                                tmp2 = new UVFaceTexture(*ft);
 
1027
                                tmp2->type = 1;
 
1028
                        }
 
1029
                        ih[fi][textureId]=tmp2;
 
1030
                                
 
1031
                        
 
1032
                        k++;
 
1033
                }
 
1034
        }
 
1035
        textureList[textureId] = "combined_"+QString::number(combineCounter);
 
1036
        combineCounter++;
 
1037
        return textureId;
 
1038
}
 
1039
 
 
1040
void PhotoTexturer::calculateZBuffer(MeshModel *mm,Camera* camera,QuadTreeNode *qtree, TextureFilterZB *zbuffer){
 
1041
        
 
1042
        qDebug()<< "zbuffer->vm_height:"<<zbuffer->vm_height<<"zbuffer->vm_width:" <<zbuffer->vm_width;
 
1043
        int x,y;
 
1044
        for (y=0;y<zbuffer->vm_height;y++){
 
1045
                for (x=0;x<zbuffer->vm_width;x++){
 
1046
                        double dx = ((double)x/(double)(zbuffer->vm_width-1));
 
1047
                        double dy = ((double)y/(double)(zbuffer->vm_height-1));
 
1048
                        QList<QuadTreeLeaf*>list;
 
1049
                        qtree->getLeafs(dx,dy,list);
 
1050
                        if(list.size()>0){
 
1051
                                int i;
 
1052
                                for (i=0;i<list.size();i++){
 
1053
                                        QuadTreeLeaf* leaf = list.at(i);
 
1054
                                        UVFaceTexture *uvft = dynamic_cast<UVFaceTexture*>(leaf);
 
1055
                                        if (uvft != 0){
 
1056
                                                double a,b,c,d;
 
1057
                                                uvft->getBarycentricCoordsForUV(dx,dy,a,b,c,d);
 
1058
                                                //qDebug() << "d:" << d;
 
1059
                                                if(d == 0.0){
 
1060
                                                        CFaceO face = mm->cm.face.at(uvft->faceIndex);
 
1061
                                                        vcg::Point3f point = face.V(0)->cP()*a+face.V(1)->cP()*b+face.V(2)->cP()*c;
 
1062
                                                        double distance = sqrt(pow(camera->calibration->cameraPosition[0]-point[0],2)+pow(camera->calibration->cameraPosition[1]-point[1],2)+pow(camera->calibration->cameraPosition[2]-point[2],2));
 
1063
                                                        //qDebug()<< "distance: " << distance;
 
1064
                                                        if(zbuffer->getValue(x,y)== DBL_MIN||zbuffer->getValue(x,y)>distance){
 
1065
                                                                zbuffer->setValue(x,y,distance);
 
1066
                                                                //qDebug()<< "found z";
 
1067
                                                        }
 
1068
                                                }else{
 
1069
                                
 
1070
                                                }
 
1071
                                        }
 
1072
                                        
 
1073
                                }
 
1074
                        }
 
1075
                }
 
1076
        }
 
1077
        
 
1078
}
 
1079
 
 
1080
void PhotoTexturer::reset(MeshModel *mm){
 
1081
        if (origTextureID > -1){
 
1082
                restoreOriginalTextureCoordinates(mm);
 
1083
        }else{
 
1084
                mm->clearDataMask(MeshModel::MM_WEDGTEXCOORD);
 
1085
        }
 
1086
        
 
1087
        
 
1088
        QList<int> keys = textureList.keys(); 
 
1089
        
 
1090
        
 
1091
        for(int i =0; i< keys.size();i++){
 
1092
                int key = keys[i];
 
1093
                if(key != origTextureID){
 
1094
                        QMap<int, QString>::const_iterator it = textureList.find(key);
 
1095
                        if (it != textureList.end()){
 
1096
                                if (vcg::tri::HasPerFaceAttribute(mm->cm,UVTEXTURECOORDS)){
 
1097
                                
 
1098
                                        CMeshO::PerFaceAttributeHandle<QMap<int,UVFaceTexture*> > ih = vcg::tri::Allocator<CMeshO>::GetPerFaceAttribute<QMap<int,UVFaceTexture*> > (mm->cm,UVTEXTURECOORDS);
 
1099
                                        CMeshO::FaceIterator fi;
 
1100
                                        for(fi=mm->cm.face.begin(); fi!=mm->cm.face.end(); ++fi) {
 
1101
                                                int i;
 
1102
                                                UVFaceTexture* ft = ih[fi][key];
 
1103
                                                delete ft;
 
1104
                                                ih[fi].remove(key);
 
1105
                                        }
 
1106
                                        //m->cm
 
1107
                                }
 
1108
                        }
 
1109
                        textureList.remove(key);
 
1110
                }
 
1111
        }
 
1112
        
 
1113
        for(int i = 0;i<cameras.size();i++){
 
1114
                Camera *c = cameras.at(i);
 
1115
                delete c;
 
1116
                cameras.clear();
 
1117
        }
 
1118
}
 
1119