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/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/algorithms/update/position.h>
53 #include <vcg/complex/algorithms/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
PhotoTexturer()90 PhotoTexturer::PhotoTexturer(){
91 origTextureID = -1;
92 nextTextId = 0;
93 bakeCounter = 0;
94 combineCounter = 0;
95 }
~PhotoTexturer()96 PhotoTexturer::~PhotoTexturer(){
97
98 }
99
loadConfigurationFile(QString cfgFile)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
generateTextureId()119 int PhotoTexturer::generateTextureId(){
120 return ++nextTextId;
121 }
122
saveConfigurationFile(QString cfgFile)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
addCamera(QString camFile)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
removeCamera(int i)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
storeOriginalTextureCoordinates(MeshModel * m)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
restoreOriginalTextureCoordinates(MeshModel * m)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
calculateMeshTextureForAllCameras(MeshModel * m,bool calcZBuffer)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
calculateMeshTextureForCamera(MeshModel * m,Camera * cam,bool calcZBuffer)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
applyTextureToMesh(MeshModel * m,int textureIdx,bool use_different_tidx,int tidx)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
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)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 }
getSurrundingMeanColor(QRgb * uimg,int iwidth,int iheight,int x,int y,QColor & surcolor)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
edgeTextureStretching(QImage * image,int pass)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
unprojectTextures(MeshModel * m,int textureID,FilterParameterSet * paraSet)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
bakeTextures(MeshModel * m,FilterParameterSet * paraSet)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
mergeTextureImagesWinnerTakesAll(int imgWidth,int imgHeight,QList<QImage> imgList)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
convertToTsaiCamera(int camIdx,bool optimize,QString filename,MeshModel * mm)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
exportMaxScript(QString filename,MeshModel * mm)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
combineTextures(MeshModel * m)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
calculateZBuffer(MeshModel * mm,Camera * camera,QuadTreeNode * qtree,TextureFilterZB * zbuffer)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
reset(MeshModel * mm)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
1120