/*========================================================================= Program: Visualization Toolkit Module: vtkVolumeMask.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef vtkVolumeMask_h #define vtkVolumeMask_h #include #include #include #include #include #include #include // STL required //---------------------------------------------------------------------------- class vtkVolumeMask { public: //-------------------------------------------------------------------------- vtkVolumeMask() { this->Texture = nullptr; this->Loaded = false; this->LoadedExtent[0] = VTK_INT_MAX; this->LoadedExtent[1] = VTK_INT_MIN; this->LoadedExtent[2] = VTK_INT_MAX; this->LoadedExtent[3] = VTK_INT_MIN; this->LoadedExtent[4] = VTK_INT_MAX; this->LoadedExtent[5] = VTK_INT_MIN; } //-------------------------------------------------------------------------- ~vtkVolumeMask() { if (this->Texture) { this->Texture->Delete(); this->Texture = nullptr; } } //-------------------------------------------------------------------------- vtkTimeStamp GetBuildTime() { return this->BuildTime; } //-------------------------------------------------------------------------- void Activate() { this->Texture->Activate(); } //-------------------------------------------------------------------------- void Deactivate() { this->Texture->Deactivate(); } //-------------------------------------------------------------------------- void Update(vtkRenderer* ren, vtkImageData *input, int cellFlag, int textureExtent[6], int scalarMode, int arrayAccessMode, int arrayId, const char* arrayName, vtkIdType maxMemoryInBytes) { bool needUpdate = false; bool modified = false; if (!this->Texture) { this->Texture = vtkTextureObject::New(); needUpdate = true; } this->Texture->SetContext(vtkOpenGLRenderWindow::SafeDownCast( ren->GetRenderWindow())); if (!this->Texture->GetHandle()) { needUpdate = true; } int obsolete = needUpdate || !this->Loaded || input->GetMTime()>this->BuildTime; if(!obsolete) { obsolete = cellFlag != this->LoadedCellFlag; int i = 0; while(!obsolete && i<6) { obsolete = obsolete || this->LoadedExtent[i]>textureExtent[i]; ++i; obsolete = obsolete || this->LoadedExtent[i]Loaded = false; int dim[3]; input->GetDimensions(dim); vtkDataArray *scalars = vtkAbstractMapper::GetScalars(input,scalarMode,arrayAccessMode, arrayId,arrayName, this->LoadedCellFlag); // DON'T USE GetScalarType() or GetNumberOfScalarComponents() on // ImageData as it deals only with point data... int scalarType = scalars->GetDataType(); if(scalarType != VTK_UNSIGNED_CHAR) { cout <<"Mask should be VTK_UNSIGNED_CHAR." << endl; } if(scalars->GetNumberOfComponents()!=1) { cout << "Mask should be a one-component scalar field." << endl; } GLint internalFormat = GL_R8; GLenum format = GL_RED; GLenum type = GL_UNSIGNED_BYTE; // Enough memory? int textureSize[3]; int i = 0; while(i < 3) { textureSize[i] = textureExtent[2*i+1] - textureExtent[2*i] + 1; ++i; } GLint width; glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &width); this->Loaded = textureSize[0] <= width && textureSize[1] <= width && textureSize[2] <= width; if(this->Loaded) { // so far, so good but some cards don't report allocation error this->Loaded = textureSize[0] * textureSize[1]* textureSize[2] * vtkAbstractArray::GetDataTypeSize(scalarType) * scalars->GetNumberOfComponents() <= maxMemoryInBytes; if(this->Loaded) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if(!(textureExtent[1]-textureExtent[0]+cellFlag==dim[0])) { glPixelStorei(GL_UNPACK_ROW_LENGTH,dim[0]-cellFlag); } if(!(textureExtent[3]-textureExtent[2]+cellFlag==dim[1])) { glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, dim[1]-cellFlag); } void* dataPtr = scalars->GetVoidPointer( ((textureExtent[4]*(dim[1]-cellFlag)+textureExtent[2]) * (dim[0]-cellFlag)+textureExtent[0]) * scalars->GetNumberOfComponents()); this->Texture->SetDataType(type); this->Texture->SetFormat(format); this->Texture->SetInternalFormat(internalFormat); this->Texture->Create3DFromRaw( textureSize[0], textureSize[1], textureSize[2], 1, scalarType, dataPtr); this->Texture->SetWrapS(vtkTextureObject::ClampToEdge); this->Texture->SetWrapT(vtkTextureObject::ClampToEdge); this->Texture->SetWrapR(vtkTextureObject::ClampToEdge); this->Texture->SetMagnificationFilter(vtkTextureObject::Nearest); this->Texture->SetMinificationFilter(vtkTextureObject::Nearest); this->Texture->SetBorderColor(0.0f, 0.0f, 0.0f, 0.0f); // Restore the default values. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); this->LoadedCellFlag = cellFlag; i = 0; while(i < 6) { this->LoadedExtent[i] = textureExtent[i]; ++i; } double spacing[3]; double origin[3]; input->GetSpacing(spacing); input->GetOrigin(origin); int swapBounds[3]; swapBounds[0] = (spacing[0] < 0); swapBounds[1] = (spacing[1] < 0); swapBounds[2] = (spacing[2] < 0); if(!this->LoadedCellFlag) // loaded extents represent points { // slabsPoints[i]=(slabsDataSet[i] - origin[i/2]) / spacing[i/2]; // in general, x=o+i*spacing. // if spacing is positive min extent match the min of the // bounding box // and the max extent match the max of the bounding box // if spacing is negative min extent match the max of the // bounding box // and the max extent match the min of the bounding box // if spacing is negative, we may have to rethink the equation // between real point and texture coordinate... this->LoadedBounds[0]=origin[0]+ static_cast(this->LoadedExtent[0+swapBounds[0]])*spacing[0]; this->LoadedBounds[2]=origin[1]+ static_cast(this->LoadedExtent[2+swapBounds[1]])*spacing[1]; this->LoadedBounds[4]=origin[2]+ static_cast(this->LoadedExtent[4+swapBounds[2]])*spacing[2]; this->LoadedBounds[1]=origin[0]+ static_cast(this->LoadedExtent[1-swapBounds[0]])*spacing[0]; this->LoadedBounds[3]=origin[1]+ static_cast(this->LoadedExtent[3-swapBounds[1]])*spacing[1]; this->LoadedBounds[5]=origin[2]+ static_cast(this->LoadedExtent[5-swapBounds[2]])*spacing[2]; } else // loaded extents represent cells { int wholeTextureExtent[6]; input->GetExtent(wholeTextureExtent); i=1; while(i<6) { wholeTextureExtent[i]--; i+=2; } i=0; while(i<3) { if(this->LoadedExtent[2*i]==wholeTextureExtent[2*i]) { this->LoadedBounds[2*i+swapBounds[i]]=origin[i]; } else { this->LoadedBounds[2*i+swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i])+0.5)*spacing[i]; } if(this->LoadedExtent[2*i+1]==wholeTextureExtent[2*i+1]) { this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i+1])+1.0)*spacing[i]; } else { this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i+1])+0.5)*spacing[i]; } ++i; } } modified = true; } } } if(modified) { this->BuildTime.Modified(); } } //-------------------------------------------------------------------------- double* GetLoadedBounds() { return this->LoadedBounds; } //-------------------------------------------------------------------------- vtkIdType* GetLoadedExtent() { return this->LoadedExtent; } //-------------------------------------------------------------------------- int GetLoadedCellFlag() { return this->LoadedCellFlag; } //-------------------------------------------------------------------------- bool IsLoaded() { return this->Loaded; } // Get the texture unit //-------------------------------------------------------------------------- int GetTextureUnit(void) { if (!this->Texture) { return -1; } return this->Texture->GetTextureUnit(); } //-------------------------------------------------------------------------- void ReleaseGraphicsResources(vtkWindow *window) { if (this->Texture) { this->Texture->ReleaseGraphicsResources(window); this->Texture->Delete(); this->Texture = nullptr; } } protected: vtkTextureObject* Texture; vtkTimeStamp BuildTime; double LoadedBounds[6]; vtkIdType LoadedExtent[6]; int LoadedCellFlag; bool Loaded; }; //---------------------------------------------------------------------------- class vtkMapMaskTextureId { public: std::map Map; vtkMapMaskTextureId() { } private: vtkMapMaskTextureId(const vtkMapMaskTextureId &other); vtkMapMaskTextureId &operator=(const vtkMapMaskTextureId &other); }; #endif // vtkVolumeMask_h // VTK-HeaderTest-Exclude: vtkVolumeMask.h