00001 #include <stdio.h>
00002 #include <fstream.h>
00003 #include <math.h>
00004
00005 #include "SheetSplat.h"
00006
00007 #include "vuColour7a.h"
00008 #include "vuColour31a.h"
00009 #include "vuColourXYZa.h"
00010 #include "vuColourRGBa.h"
00011 #include "vuColourSpec.h"
00012
00013 #define SHSP_SPLAT_CROP_RATIO 0.0 // ratio of slice width below which splat is ignored
00014 #define SHSP_SPLATSTDSCALE 1 // scaling for the standard deviation of the splat is scaled
00015
00016 #define SHSP_SPLATRADIUS 2.3 // changed from 1.6
00017
00018
00019
00020 #define SHSP_SHEETWIDTH 1
00021
00022
00023
00024
00025
00026
00027
00028
00032 float pow(float b, unsigned int e)
00033 {
00034 float r = 1;
00035 while(e) {
00036 if(e&1) r*=b;
00037 b*=b;
00038 e=e>>1;
00039 }
00040
00041 vuColourXYZa xyz;
00042 xyz.from(vuColourRGBa(1));
00043 return r;
00044 }
00045
00046
00047
00048
00049
00050 vu1512112::vu1512112()
00051 {
00052
00053
00054 m_DataPrepared = false;
00055 m_SplatPos = NULL;
00056 m_Slices = NULL;
00057 m_SliceDist = NULL;
00058 setSliceWidth(SHSP_SHEETWIDTH);
00059 setFootprintSize(SHSP_SPLATRADIUS);
00060 m_Normals = NULL;
00061 m_Shading = NULL;
00062 m_LightDir = vuVector(-1,0,0);
00063 m_LightDiffuse = 0.9;
00064 m_LightAmbient = 0.1;
00065 float scol[] = {1,1,1,0};
00066 m_LightSpecular = vuColourRGBa(scol);
00067 m_LightShininess = 20;
00068 setBGColour(0,0,0);
00069 setImageSize(200,200);
00070
00071 m_Camera = new vuParallelCamera;
00072 }
00073
00074
00075
00076
00077
00078 vu1512112::~vu1512112()
00079 {
00080 clearSheets();
00081 if (m_Camera != NULL) {
00082 delete m_Camera;
00083 m_Camera = NULL;
00084 }
00085 }
00086
00087
00088
00089
00090
00091 vu1512112& vu1512112::operator=(const vu1512112& rhs)
00092 {
00093 if (this != &rhs)
00094 {
00095 vu151211::operator=(rhs);
00096 }
00097 return *this;
00098 }
00099
00100
00101
00102
00103
00104 float vu1512112::getFootprintSize() const
00105 {
00106 return m_SplatRadius;
00107 }
00108
00109
00110
00111
00112
00113 void vu1512112::setFootprintSize(float size)
00114 {
00115 m_SplatRadius = size;
00116 m_SpS_2 = int(m_SplatRadius/m_SliceWidth)+1;
00117 }
00118
00119
00120
00121 float vu1512112::getSliceWidth() const
00122 {
00123 return m_SliceWidth;
00124 }
00125
00126
00127
00128 void vu1512112::setSliceWidth(const float size)
00129 {
00130 if(size<0.05) m_SliceWidth = 0.05;
00131 else m_SliceWidth = size;
00132 m_SpS_2 = int(m_SplatRadius/m_SliceWidth)+1;
00133 m_SplatCrop = m_SliceWidth*SHSP_SPLAT_CROP_RATIO;
00134 }
00135
00136
00137
00138
00139
00140 void vu1512112::setViewVectors(const vuVector& view,const vuVector& up,const vuVector& right)
00141 {
00142
00143 }
00144
00145
00146
00147
00148
00149 bool vu1512112::read()
00150 {
00151 bool success = vu151211::read();
00152 if (!success) return false;
00153
00154 m_Center = getVoxelPosition(m_Dim1Size, m_Dim2Size, m_Dim3Size);
00155 m_Center *= 0.5;
00156 m_Camera->setPosition(m_Center);
00157 m_Camera->translateXYZ(0,0,-100);
00158
00159 cout<<"cpos";
00160 m_Camera->getPosition().print();
00161
00162
00163 if (m_Normals != 0) delete [] m_Normals;
00164 m_Normals = new vuVector[m_DataSize];
00165 if (m_Shading != 0) delete [] m_Shading;
00166 m_Shading = new float[m_DataSize*2];
00167
00168 if (m_SplatPos != 0) delete m_SplatPos;
00169 m_SplatPos = new float[m_DataSize*3];
00170
00171
00172 preprocess();
00173 return true;
00174 }
00175
00176 void vu1512112::showHistogram()
00177 {
00178 dword hist[256];
00179 dword i;
00180 for(i=0;i<256;i++)
00181 hist[i]=0;
00182 byte *dat = m_Data;
00183 for(i=0;i<m_DataSize;i++,dat++)
00184 hist[*dat]++;
00185 for(i=0;i<256;i++)
00186 printf("[%i]=%i ",int(i),int(hist[i]));
00187 putchar('n');
00188 }
00189
00190
00191
00192
00193
00194 bool vu1512112::readRaw(void)
00195 {
00196 dword len;
00197 ifstream in;
00198
00199
00200 #ifdef IS_NOCREATE_NEEDED
00201 in.open(m_FileName, ios::in|ios::binary|ios::nocreate);
00202 #else
00203
00204
00205 in.open(m_FileName, ios::in|ios::binary);
00206 #endif
00207 if (!in.is_open()) return false;
00208
00209 in.seekg(0, ios::end);
00210 len = in.tellg();
00211 in.seekg(0, ios::beg);
00212
00213 in >> m_Dim1Size >> m_Dim2Size >> m_Dim3Size;
00214 if (in.fail()) return false;
00215 m_DataSize = m_Dim1Size*m_Dim2Size*m_Dim3Size;
00216
00217 m_Data = new byte[m_DataSize];
00218 in.read((char *)m_Data, (int)m_DataSize);
00219 if (in.fail()) return false;
00220
00221 in.close();
00222
00223 m_Center = getVoxelPosition(m_Dim1Size, m_Dim2Size, m_Dim3Size);
00224 m_Center *= 0.5;
00225 m_Camera->setPosition(m_Center);
00226 m_Camera->translateXYZ(0,0,-100);
00227
00228 cout<<"cpos";
00229 m_Camera->getPosition().print();
00230
00231
00232 if (m_Normals != 0) delete [] m_Normals;
00233 m_Normals = new vuVector[m_DataSize];
00234 if (m_Shading != 0) delete [] m_Shading;
00235 m_Shading = new float[m_DataSize*2];
00236
00237 if (m_SplatPos != 0) delete m_SplatPos;
00238 m_SplatPos = new float[m_DataSize*3];
00239
00240 preprocess();
00241
00242 return true;
00243 }
00244
00245
00246
00247
00248
00249 void vu1512112::preprocess(void)
00250 {
00251
00252
00253 dword w, wh;
00254 dword i, j, k, index;
00255
00256 w = m_Dim1Size;
00257 wh = m_Dim1Size*m_Dim2Size;
00258
00259
00260
00261
00262
00263 index = 0;
00264 for(k=0;k<m_Dim3Size;++k)
00265 {
00266 for(j=0;j<m_Dim2Size;++j)
00267 {
00268 for(i=0;i<m_Dim1Size;++i)
00269 {
00270 if (i == 0)
00271 m_Normals[index][0] = m_Data[index+1]-m_Data[index];
00272 else if (i == m_Dim1Size-1)
00273 m_Normals[index][0] = m_Data[index]-m_Data[index-1];
00274 else
00275 m_Normals[index][0] = (m_Data[index+1]-m_Data[index-1])*0.5;
00276
00277 if (j == 0)
00278 m_Normals[index][1] = m_Data[index+w]-m_Data[index];
00279 else if (j == m_Dim2Size-1)
00280 m_Normals[index][1] = m_Data[index]-m_Data[index-w];
00281 else
00282 m_Normals[index][1] = (m_Data[index+w]-m_Data[index-w])*0.5;
00283
00284 if ((k == 0) || (k == 1))
00285 m_Normals[index][2] = m_Data[index+2*wh]-m_Data[index];
00286 else if ((k == m_Dim3Size-1) || (k == m_Dim3Size-2))
00287 m_Normals[index][2] = m_Data[index]-m_Data[index-2*wh];
00288 else
00289 m_Normals[index][2] = (m_Data[index+2*wh]-m_Data[index-2*wh])*0.5;
00290
00291 m_Normals[index].makeUnit();
00292
00293 ++index;
00294 }
00295 }
00296 }
00297
00298 m_DataPrepared = true;
00299 }
00300
00301
00302 void vu1512112::setBGColour(float r, float g, float b)
00303 {
00304 m_BGColour[0] = r;
00305 m_BGColour[1] = g;
00306 m_BGColour[2] = b;
00307 m_BGColour[3] = 0;
00308 }
00309
00310 void vu1512112::run(int whatsup, void* data)
00311 {
00312 drawSlices();
00313 }
00314
00315
00316
00317
00318
00319 void vu1512112::drawSlices()
00320 {
00321 float black[] = {0,0,0,0};
00322 RGBABuffer sheetBuffer;
00323 sheetBuffer.setSize(m_FBWidth, m_FBHeight);
00324 int cs;
00325 while((cs=m_CurrentSheet++)<m_NSlices) {
00326 sheetBuffer.clear(vuColourRGBa(black));
00327 drawSlice(sheetBuffer, cs);
00328 m_FBMutex.lock();
00329 m_FrameBuffer.blendUnder(sheetBuffer);
00330 m_FBMutex.unlock();
00331 cout<<'.'<<flush;
00332 }
00333 }
00334
00335 void vu1512112::render(void)
00336 {
00337 if(!m_Data || !m_DataPrepared) return;
00338
00339 int i,j;
00340
00341 if(m_Refresh) {
00342
00343
00344 int pixsize = int(ceil(m_Camera->getWidth()/((vuParallelCamera *)m_Camera)->getXRange()*2*m_SplatRadius));
00345 int piysize = int(ceil(m_Camera->getHeight()/((vuParallelCamera *)m_Camera)->getYRange()*2*m_SplatRadius));
00346 m_Splat.buildSplat(m_SplatRadius/SHSP_SPLATSTDSCALE,pixsize, piysize,128);
00347
00348
00349 for(i=0; i<256; i++) {
00350 m_Exclude[i] = m_TFunc[i][3] < 0.001;
00351 }
00352
00353 cout<<"sorting..."<<endl;
00354 sortByDistance();
00355
00356 cout<<"drawing"<<flush;
00357
00358 m_FrameBuffer.clear(m_BGColour);
00359 m_CurrentSheet = 0;
00360
00361 startThread(0);
00362 drawSlices();
00363
00364 cout<<endl;
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 m_Refresh = false;
00376 }
00377
00378 fbtype *fbuf = m_FrameBuffer.getData();
00379 byte *sbuf = new byte[3*m_FBHeight*m_FBWidth];
00380 byte *screen = sbuf;
00381 if(!sbuf) return;
00382 for(i=0;i<m_FBHeight;i++)
00383 for(j=0;j<m_FBWidth;j++) {
00384 #ifdef FB_FLOAT
00385 if(*fbuf>1) *fbuf = 1;
00386 else if(*fbuf<0) *fbuf = 0;
00387 *(screen++) = int(*(fbuf++)*255);
00388 if(*fbuf>1) *fbuf = 1;
00389 else if(*fbuf<0) *fbuf = 0;
00390 *(screen++) = int(*(fbuf++)*255);
00391 if(*fbuf>1) *fbuf = 1;
00392 else if(*fbuf<0) *fbuf = 0;
00393 *(screen++) = int(*(fbuf++)*255);
00394 #else
00395 *(screen++) = (*(fbuf++))>>8;
00396 *(screen++) = (*(fbuf++))>>8;
00397 *(screen++) = (*(fbuf++))>>8;
00398 #endif
00399 fbuf++;
00400 }
00401 glRasterPos2f(0,0);
00402 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
00403 glDrawPixels(m_FBWidth,m_FBHeight,GL_RGB,GL_UNSIGNED_BYTE,sbuf);
00404 delete sbuf;
00405 }
00406
00407
00408 bool vu1512112::setImageSize(int width, int height)
00409 {
00410 if(!m_FrameBuffer.setSize(width,height)) return false;
00411 m_FrameBuffer.clear(m_BGColour);
00412 m_Camera->setWidth(width);
00413 m_Camera->setHeight(height);
00414 m_FBWidth = width;
00415 m_FBHeight = height;
00416
00417 return true;
00418 }
00419
00420
00421
00422
00423
00424 void vu1512112::initOpenGL(void)
00425 {
00426 }
00427
00428 void vu1512112::initSheets(float dist0, float ddist)
00429 {
00430 if(m_Slices != 0) clearSheets();
00431 m_Slices = new dword*[m_NSlices];
00432 m_SliceDist = new float[m_NSlices];
00433 if(!m_Slices) return;
00434 int i;
00435 for(i=0;i<m_NSlices;i++) {
00436 m_Slices[i] = new dword[1];
00437 m_Slices[i][0] = 0;
00438 m_SliceDist[i] = dist0+i*ddist;
00439 }
00440 }
00441
00442 void vu1512112::prepareSheets()
00443 {
00444 if(m_Slices == 0) return;
00445 int i;
00446 for(i=0;i<m_NSlices;i++) {
00447 int n = m_Slices[i][0]+1;
00448 delete [] m_Slices[i];
00449 m_Slices[i] = new dword[n];
00450 m_Slices[i][0] = 1;
00451 }
00452 }
00453
00454 void vu1512112::clearSheets()
00455 {
00456 if(m_Slices == 0) return;
00457 int i;
00458 for(i=0;i<m_NSlices;i++)
00459 delete [] m_Slices[i];
00460 delete [] m_Slices;
00461 delete [] m_SliceDist;
00462 m_SliceDist = NULL;
00463 m_Slices = NULL;
00464 }
00465
00466 void vu1512112::sortByDistance()
00467 {
00468 if(m_Dim1Size<2) return;
00469
00470 m_LightDir = m_Center;
00471 m_LightDir -= m_Camera->getPosition();
00472 m_LightDir.makeUnit();
00473
00474 clearSheets();
00475
00476
00477
00478 vuVector ldir = m_Camera->getPosition();
00479 ldir -= m_Center;
00480
00481 int nx,ny,nz;
00482 nx = (ldir[0]>0);
00483 ny = (ldir[1]>0);
00484 nz = (ldir[2]>0);
00485
00486 int splatslices = int(m_SplatRadius*2/m_SliceWidth)+1;
00487
00488 float nearest = ((vuParallelCamera *)m_Camera)->getDistance(getVoxelPosition(m_Dim1Size*nx,
00489 m_Dim2Size*ny,
00490 m_Dim3Size*nz));
00491 float farest = ((vuParallelCamera *)m_Camera)->getDistance(getVoxelPosition(m_Dim1Size* (!nx),
00492 m_Dim2Size* (!ny),
00493 m_Dim3Size* (!nz)));
00494 nearest -= (splatslices*m_SliceWidth)/2;
00495 farest += (splatslices*m_SliceWidth)/2;
00496 m_NSlices = (int)ceil((farest-nearest)/m_SliceWidth) + 2;
00497 farest = nearest+ m_SliceWidth*m_NSlices;
00498 printf("near = %4.4f far = %4.4f nslices = %i\n", nearest, farest, m_NSlices);
00499
00500 initSheets(nearest,m_SliceWidth);
00501
00502 dword i,j,k;
00503 int index=0, index3=0;
00504 float sd;
00505 dword sind;
00506
00507 for(k=0;k<m_Dim3Size;k++) {
00508 for(j=0;j<m_Dim2Size;j++) {
00509 index = 0+(j*m_Dim1Size)+(k*m_Dim1Size*m_Dim2Size);
00510 index3 = index*3;
00511 vuVector p0 = getVoxelPosition(0,j,k);
00512 vuVector pr0= p0;
00513 ((vuParallelCamera *)m_Camera)->project(pr0);
00514 memcpy(&m_SplatPos[index3],pr0.getData(),sizeof(float)*3);
00515 if(!m_Exclude[m_Data[index]]) {
00516 sd = m_SplatPos[index3+2]-nearest;
00517 sind = int(sd/m_SliceWidth);
00518 dword lslice = sind+m_SpS_2+1;
00519 for(sind = sind-m_SpS_2;sind<lslice;sind++)
00520 m_Slices[sind][0]++;
00521 m_Shading[index<<1] = m_LightDir.dot(m_Normals[index]);
00522 }
00523
00524 index = 1+(j*m_Dim1Size)+(k*m_Dim1Size*m_Dim2Size);
00525 index3 = index*3;
00526 vuVector p1 = getVoxelPosition(1,j,k);
00527 vuVector pr1= p1;
00528 ((vuParallelCamera *)m_Camera)->project(pr1);
00529 memcpy(&m_SplatPos[index3],pr1.getData(),sizeof(float)*3);
00530 if(!m_Exclude[m_Data[index]]) {
00531 sd = m_SplatPos[index3+2]-nearest;
00532 sind = int(sd/m_SliceWidth);
00533
00534 dword lslice = sind+m_SpS_2+1;
00535 for(sind = sind-m_SpS_2;sind<lslice;sind++)
00536 m_Slices[sind][0]++;
00537
00538 m_Shading[index<<1] = m_LightDir.dot(m_Normals[index]);
00539 }
00540
00541 p0 = p1-p0;
00542 pr0 = pr1-pr0;
00543
00544 for(i=2;i<m_Dim1Size;i++) {
00545 index = i+(j*m_Dim1Size)+(k*m_Dim1Size*m_Dim2Size);
00546 index3 = index*3;
00547 p1 += p0;
00548 pr1 += pr0;
00549
00550 if(!m_Exclude[m_Data[index]]) {
00551 memcpy(&m_SplatPos[index3],pr1.getData(),sizeof(float)*3);
00552 sd = m_SplatPos[index3+2]-nearest;
00553
00554
00555
00556 sind = int(sd/m_SliceWidth);
00557
00558 dword lslice = sind+m_SpS_2+1;
00559 for(sind = sind-m_SpS_2;sind<lslice;sind++)
00560 m_Slices[sind][0]++;
00561
00562
00563 vuVector& n = m_Normals[index];
00564 float d = m_LightDir.dot(n);
00565 m_Shading[index<<1] = (d > 0 ? d : 0)*m_LightDiffuse + m_LightAmbient;
00566 vuVector r = p1-m_Camera->getPosition();
00567 r.makeUnit();
00568 r -= ((2*r.dot(n))*n);
00569 float s = m_LightDir.dot(r);
00570 s = s<0 ? -s : 0;
00571 m_Shading[(index<<1)+1] = pow(s,m_LightShininess);
00572 }
00573 }
00574 }
00575 }
00576
00577
00578
00579
00580
00581
00582 prepareSheets();
00583
00584 index = index3 = 0;
00585 for(k=0;k<m_Dim3Size;k++) {
00586 for(j=0;j<m_Dim2Size;j++) {
00587 for(i=0;
00588 i<m_Dim1Size;
00589 i++) {
00590 index = i+(j*m_Dim1Size)+(k*m_Dim1Size*m_Dim2Size);
00591 index3 = index*3;
00592
00593 if(!m_Exclude[m_Data[index]]) {
00594 sd = m_SplatPos[index3+2]-nearest;
00595
00596
00597
00598 sind = int(sd/m_SliceWidth);
00599
00600 if(sind>0 && sind<(dword)m_NSlices-1) {
00601 dword lslice = sind+m_SpS_2+1;
00602 for(sind = sind-m_SpS_2;sind<lslice;sind++)
00603 m_Slices[sind][m_Slices[sind][0]++] = index;
00604 }
00605 }
00606 }
00607 }
00608 }
00609 }
00610
00611 void vu1512112::drawSlice(RGBABuffer& sheet, int n)
00612 {
00613 dword *splat = &m_Slices[n][1];
00614 byte density;
00615 int w2 = int (m_Camera->getWidth()/2);
00616 int h2 = int (m_Camera->getHeight()/2);
00617 float sdist = m_SliceDist[n];
00618 for(int SC = m_Slices[n][0]-1; SC!=0; SC--, splat++) {
00619
00620 dword index = *splat;
00621 dword index3 = index*3;
00622 density = m_Data[index];
00623 float t0=sdist-m_SplatPos[index3+2];
00624 float t1=t0+m_SliceWidth;
00625
00626 vuColourRGBa col(m_TFunc[density]);
00627 col*=m_Shading[index<<1];
00628 vuColourRGBa spec = m_LightSpecular;
00631 spec*=m_Shading[(index<<1)+1];
00632 col += spec;
00633 col.clampTo01();
00634
00635 sheet.addColourWithM1subM2(m_Splat.getSpla(t1), m_Splat.getSpla(t0),
00636 col,
00637 (int) m_SplatPos[index3]+w2,
00638 (int) (h2-m_SplatPos[index3+1]));
00639 }
00640 }
00641