00001 #include "FourierSlicer.h"
00002 #include "General/vuLinAlg/vuVector.h"
00003 #include "vuLightfield/Converter/vuSphericLightfieldFile.h"
00004 #include "General/vuFourier/vuFourierFilter/vuTorstensFourierFilter.h"
00005 #include "General/vuMisc/vuTimer.h"
00006 #include <GL/gl.h>
00007 #include <GL/glut.h>
00008 #include <iostream>
00009 #include <stdio.h>
00010 #include <math.h>
00011
00012
00013
00014
00015
00016 template <int S>
00017 FourierSlicer<S>::FourierSlicer(vuString fileName, dword views,
00018 float scale, float bias,
00019 vuString filterName,
00020 vuString timingFileName)
00021 {
00022 m_NumOfViews = views;
00023 m_TimingStream = NULL;
00024
00025 if (!timingFileName.isEmpty())
00026 m_TimingStream = new ofstream(timingFileName, ios::out);
00027
00028 cerr << "calculate view directions..." << endl;
00029
00030 m_Sphere = new vuUDSphere(views);
00031 m_Sphere->lazyCalculate();
00032
00033 cerr << "initialize fourier volume..." << endl;
00034
00035 m_Fourier = new vu1712_1<S>;
00036 m_Fourier->setScale(scale);
00037 m_Fourier->setBias(bias);
00038 vuFourierFilter *filter = vuTorstensFourierFilter::getFilter(filterName);
00039 if (filter == NULL) {
00040 cerr << "WARNING: Could not load filter with name: '";
00041 cerr << filterName << "' use 'd0_c3_2ef' instead." << endl;
00042 filter = vuTorstensFourierFilter::getFilter("d0_c3_2ef");
00043 filterName = "d0_c3_2ef";
00044 }
00045 m_Fourier->setFilter(filter);
00046
00047 m_Fourier->setFileName(fileName);
00048 if (m_Fourier->read()) {
00049 m_Width = m_Fourier->getImageWidth();
00050 m_Height = m_Fourier->getImageHeight();
00051
00052 m_ExternalWidth = (dword)((float)m_Width / M_SQRT2);
00053 m_ExternalHeight = (dword)((float)m_Height / M_SQRT2);
00054
00055 if (((m_Width - m_ExternalWidth) % 2) == 1) m_ExternalWidth -= 1;
00056 if (((m_Height - m_ExternalHeight) % 2) == 1) m_ExternalHeight -= 1;
00057
00058 cerr << endl;
00059 cerr << "********************************************************" << endl;
00060 cerr << "views = " << views << endl;
00061 cerr << "scale = " << scale << endl;
00062 cerr << "bias = " << bias << endl;
00063 cerr << "dimension = " << m_ExternalWidth << "x" << m_ExternalHeight<<endl;
00064 cerr << "channels = " << S << endl;
00065 cerr << "filter = " << filterName << endl;
00066 cerr << "********************************************************" << endl;
00067 cerr << endl;
00068
00069 m_isComputed = false;
00070 }
00071 else {
00072 m_isComputed = true;
00073 cerr << "ERROR: could not load '" << fileName << "'" << endl;
00074 }
00075
00076 if (m_TimingStream != NULL) {
00077 *m_TimingStream<<" file: "<<fileName.getLastPathComponent()<<endl;
00078 *m_TimingStream<< " filter: " << filterName << endl;
00079 *m_TimingStream<< " views: " << views << endl;
00080 *m_TimingStream<< " dimensions: "<<m_Fourier->getXSize()<<"^3"<< endl;
00081 *m_TimingStream<< " channels: " << S << endl;
00082 *m_TimingStream<< "implementation: template interleaved" << endl;
00083 *m_TimingStream<< endl;
00084
00085 *m_TimingStream << " lookAt ";
00086 *m_TimingStream << "timing in ms" << endl;
00087
00088 *m_TimingStream << " x y z ";
00089 *m_TimingStream << "slicing fft" << endl;
00090 }
00091 }
00092
00093 template <int S>
00094 FourierSlicer<S>::~FourierSlicer()
00095 {
00096 CHECKNDELETE(m_Fourier);
00097 CHECKNDELETE(m_Sphere);
00098 CHECKNDELETE(m_TimingStream);
00099 }
00100
00101 template <int S>
00102 void FourierSlicer<S>::lazyCalculateAndDisplay(const char *fileName)
00103 {
00104 _lazyCalculate(fileName, true);
00105 }
00106
00107 template <int S>
00108 void FourierSlicer<S>::lazyCalculateAndLog(const char *fileName)
00109 {
00110 _lazyCalculate(fileName, false);
00111 }
00112
00113 template <int S>
00114 dword FourierSlicer<S>::getImageWidth()
00115 {
00116 return m_ExternalWidth;
00117 }
00118
00119 template <int S>
00120 dword FourierSlicer<S>::getImageHeight()
00121 {
00122 return m_ExternalHeight;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132 template <int S>
00133 void FourierSlicer<S>::_initTransferFunction()
00134 {
00135
00136 }
00137
00138
00139 template <int S>
00140 void FourierSlicer<S>::_renderView(dword idx, vuSphericView<S,byte> *view,
00141 bool verbose)
00142 {
00143 Point3d point = m_Sphere->getPointAt(idx);
00144 vuVector lookAt(point.x, point.y, point.z);
00145 vuVector up(0,1,0);
00146 vuVector right;
00147
00148 lookAt *= -1;
00149 m_Fourier->calcViewVectors(lookAt, up, right);
00150
00151
00152 if (verbose) {
00153 cerr << "render view: ";
00154 cerr.width(_numberOfDigits(m_NumOfViews - 1));
00155 cerr << idx << " ";
00156 }
00157
00158 m_Fourier->setViewVectors(lookAt, up, right);
00159 if (m_TimingStream != NULL) {
00160 double time1 = vuTimer::getMilliSecondsAsDouble();
00161 m_Fourier->interpolateSlice();
00162 double time2 = vuTimer::getMilliSecondsAsDouble();
00163 m_Fourier->transformSlice();
00164 double time3 = vuTimer::getMilliSecondsAsDouble();
00165
00166 m_TimingStream->setf(ios::fixed|ios::showpoint);
00167 m_TimingStream->width(12);
00168 *m_TimingStream << lookAt[0];
00169 m_TimingStream->width(12);
00170 *m_TimingStream << lookAt[1];
00171 m_TimingStream->width(12);
00172 *m_TimingStream << lookAt[2];
00173 m_TimingStream->width(14);
00174 *m_TimingStream << time2 - time1;
00175 m_TimingStream->width(14);
00176 *m_TimingStream << time3 - time2;
00177 *m_TimingStream << endl;
00178 m_Fourier->computeUnscaledImage(false);
00179 }
00180 else
00181 m_Fourier->computeUnscaledImage();
00182
00183
00184 float *src = m_Fourier->getUnscaledImage()->getBuffer();
00185 byte *dest = view->getMap()->getBuffer();
00186 float scale = m_Fourier->getScale();
00187 float bias = m_Fourier->getBias();
00188
00189 dword Xborder = (m_Width - m_ExternalWidth) / 2;
00190 dword Yborder = (m_Height - m_ExternalHeight) / 2;
00191
00192 src += Yborder * m_Width * S;
00193 for (dword j=0; j<m_ExternalHeight; j++) {
00194 src += Xborder * S;
00195 for (dword i=0; i<m_ExternalWidth; i++) {
00196 for (int k=0; k<S; k++) {
00197 register float tmp = *(src++) * scale + bias;
00198 if (tmp < 0.0f) tmp = 0.0f;
00199 else if (tmp > 255.0f) tmp = 255.0f;
00200 *(dest++) = (byte)tmp;
00201 }
00202 }
00203 src +=Xborder * S;
00204 }
00205
00206 view->setLookFrom(vuVector(point.x, point.y, point.z));
00207 view->setUp(up);
00208 cerr << "Done." << endl;
00209 }
00210
00211 template <int S>
00212 word FourierSlicer<S>::_numberOfDigits(word number)
00213 {
00214 if (number > 9999) return 5;
00215 if (number > 999) return 4;
00216 if (number > 99) return 3;
00217 if (number > 9) return 2;
00218
00219 return 1;
00220 }
00221
00222 template <int S>
00223 void FourierSlicer<S>::_lazyCalculate(const char *fileName, bool display)
00224 {
00225 if (!m_isComputed) {
00226 vuSphericLightfieldFile<S,byte> *outFile = NULL;
00227 vuSphericView<S,byte> *view = NULL;
00228
00229 view = new vuSphericView<S,byte>(m_ExternalWidth, m_ExternalHeight);
00230
00231 outFile = new vuSphericLightfieldFile<S,byte>(m_ExternalWidth,
00232 m_ExternalHeight,
00233 m_NumOfViews,fileName);
00234
00235 outFile->open();
00236 outFile->writeHeader();
00237
00238 if (display) {
00239 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00240 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00241 glutSwapBuffers();
00242 }
00243
00244 for (dword i=0; i<m_NumOfViews; i++) {
00245 if (display) {
00246 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00247 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00248 }
00249
00250 _renderView(i, view);
00251 outFile->writeView(view);
00252
00253 if (display) {
00254 view->getMap()->glRender();
00255 glutSwapBuffers();
00256 }
00257 }
00258 outFile->close();
00259 CHECKNDELETE(view);
00260 CHECKNDELETE(outFile);
00261 m_isComputed = true;
00262 }
00263 }