@@ -175,6 +175,16 @@ bool RtiBuilder::init(std::function<bool(QString stage, int percent)> *_callback
175
175
error = " PTM and HSH do not support MRGB" ;
176
176
return false ;
177
177
}
178
+ if (type == PTM) {
179
+ if (colorspace == LRGB && (nplanes != 6 && nplanes != 9 )) {
180
+ error = " PTM with LRGB colorspace supports only 6 or 9 planes" ;
181
+ return false ;
182
+ }
183
+ if (colorspace == RGB && (nplanes != 9 && nplanes != 18 )) {
184
+ error = " PTM with RGB colorspace supports only 9 or 18 planes" ;
185
+ return false ;
186
+ }
187
+ }
178
188
179
189
if ((type == RBF || type == BILINEAR) && (colorspace != MRGB && colorspace != MYCC)) {
180
190
error = " RBF and BILINEAR support only MRGB and MYCC" ;
@@ -391,41 +401,64 @@ MaterialBuilder RtiBuilder::pickBasePTM(std::vector<Vector3f> &lights) {
391
401
uint32_t dim = ndimensions*3 ;
392
402
MaterialBuilder mat;
393
403
mat.mean .resize (dim, 0.0 );
394
-
395
- Eigen::MatrixXd A (lights.size (), 6 );
404
+
405
+ Eigen::MatrixXf A (lights.size (), 6 );
396
406
for (uint32_t l = 0 ; l < lights.size (); l++) {
397
407
Vector3f &light = lights[l];
398
408
A (l, 0 ) = 1.0 ;
399
- A (l, 1 ) = double (light[0 ]);
400
- A (l, 2 ) = double (light[1 ]);
401
- A (l, 3 ) = double (light[0 ]*light[0 ]);
402
- A (l, 4 ) = double (light[0 ]*light[1 ]);
403
- A (l, 5 ) = double (light[1 ]*light[1 ]);
404
- }
405
-
406
- Eigen::MatrixXd iA = (A.transpose ()*A).inverse ()*A.transpose ();
407
-
408
- if (colorspace == LRGB) {
409
- assert (nplanes == 9 );
410
- // we could generalize for different polynomials
411
-
412
- std::vector<float > &proj = mat.proj ;
413
- proj.resize ((nplanes-3 )*ndimensions, 0.0 );
414
- for (uint32_t p = 0 ; p < nplanes-3 ; p++) {
415
- for (uint32_t k = 0 ; k < lights.size (); k++) {
416
- uint32_t off = k + p*ndimensions;
417
- proj[off] = float (iA (p, k));
409
+ A (l, 1 ) = light[0 ];
410
+ A (l, 2 ) = light[1 ];
411
+ A (l, 3 ) = light[0 ]*light[0 ];
412
+ A (l, 4 ) = light[0 ]*light[1 ];
413
+ A (l, 5 ) = light[1 ]*light[1 ];
414
+ }
415
+
416
+ if ((colorspace == LRGB && nplanes == 6 ) || (colorspace == RGB && nplanes == 9 )) {
417
+ A.conservativeResize (lights.size (), 3 );
418
+ }
419
+
420
+ Eigen::MatrixXf iA = (A.transpose ()*A).inverse ()*A.transpose ();
421
+ if (iA.hasNaN ()) {
422
+ Eigen::MatrixXf AN (lights.size (), nplanes);
423
+ for (uint32_t l = 0 ; l < lights.size (); l++) {
424
+ Vector3f &light = lights[l];
425
+ if (colorspace == LRGB) {
426
+ A (l, 0 ) = 1.0 ;
427
+ A (l, 1 ) = light[0 ];
428
+ A (l, 2 ) = light[1 ];
429
+ check for number of planes
430
+ A (l, 3 ) = light[0 ]*light[0 ];
431
+ A (l, 4 ) = light[0 ]*light[1 ];
432
+ A (l, 5 ) = light[1 ]*light[1 ];
433
+ } else {
434
+ A (l, 0 ) = 1.0 ;
435
+ A (l, 1 ) = light[0 ];
436
+ A (l, 2 ) = light[1 ];
437
+ A (l, 3 ) = light[0 ]*light[0 ];
438
+ A (l, 4 ) = light[0 ]*light[1 ];
439
+ A (l, 5 ) = light[1 ]*light[1 ];
418
440
}
419
- }
441
+ }
442
+ mat.svd .compute (A, Eigen::ComputeThinU | Eigen::ComputeThinV);
420
443
} else {
421
- assert (colorspace == RGB && nplanes == 18 );
422
-
423
- // nplanes should be 18 here!
424
- std::vector<float > &proj = mat.proj ;
425
- proj.resize (nplanes*dim, 0.0 );
426
- for (uint32_t p = 0 ; p < nplanes; p += 3 ) {
427
- for (uint32_t k = 0 ; k < lights.size (); k ++) {
428
- proj[k*3 +0 + (p+0 )*dim] = proj[k*3 +1 + (p+1 )*dim] = proj[k*3 +2 + (p+2 )*dim] = float (iA (p/3 , k));
444
+ if (colorspace == LRGB) {
445
+ // we could generalize for different polynomials
446
+
447
+ std::vector<float > &proj = mat.proj ;
448
+ proj.resize ((nplanes-3 )*ndimensions, 0.0 );
449
+ for (uint32_t p = 0 ; p < nplanes-3 ; p++) {
450
+ for (uint32_t k = 0 ; k < lights.size (); k++) {
451
+ uint32_t off = k + p*ndimensions;
452
+ proj[off] = float (iA (p, k));
453
+ }
454
+ }
455
+ } else {
456
+ std::vector<float > &proj = mat.proj ;
457
+ proj.resize (nplanes*dim, 0.0 );
458
+ for (uint32_t p = 0 ; p < nplanes; p += 3 ) {
459
+ for (uint32_t k = 0 ; k < lights.size (); k ++) {
460
+ proj[k*3 +0 + (p+0 )*dim] = proj[k*3 +1 + (p+1 )*dim] = proj[k*3 +2 + (p+2 )*dim] = float (iA (p/3 , k));
461
+ }
429
462
}
430
463
}
431
464
}
@@ -1924,15 +1957,22 @@ std::vector<float> RtiBuilder::toPrincipal(Pixel &pixel, MaterialBuilder &materi
1924
1957
1925
1958
1926
1959
} else { // RGB, YCC
1927
- vector<float > col (dim);
1960
+ if (!materialbuilder.svd .computeU ()) { // not rank deficient.
1961
+ vector<float > col (dim);
1928
1962
1929
- for (size_t k = 0 ; k < dim; k++)
1930
- col[k] = v[k] - materialbuilder.mean [k];
1963
+ for (size_t k = 0 ; k < dim; k++)
1964
+ col[k] = v[k] - materialbuilder.mean [k];
1931
1965
1932
- for (size_t p = 0 ; p < nplanes; p++) {
1933
- for (size_t k = 0 ; k < dim; k++) {
1934
- res[p] += col[k] * materialbuilder.proj [k + p*dim];
1966
+ for (size_t p = 0 ; p < nplanes; p++) {
1967
+ for (size_t k = 0 ; k < dim; k++) {
1968
+ res[p] += col[k] * materialbuilder.proj [k + p*dim];
1969
+ }
1935
1970
}
1971
+ } else {
1972
+ Eigen::Map<Eigen::VectorXf> ev (v, ndimensions*3 );
1973
+ Eigen::Map<Eigen::VectorXf> eres (&*res.begin (), nplanes);
1974
+
1975
+ eres = materialbuilder.svd .solve (ev);
1936
1976
}
1937
1977
if (colorspace == YCC) {
1938
1978
int count = 0 ;
0 commit comments