void TransFuncProperty::fitDomainToData() { if (TransFunc1DKeys* tfi = dynamic_cast<TransFunc1DKeys*>(value_)) { //set gamma value to default tfi->setGammaValue(1.f); //set default, if no volume is present if(!volume_) { tfi->setDomain(tgt::vec2(0.f, 1.f)); invalidate(); return; } RealWorldMapping rwm = volume_->getRealWorldMapping(); if (volume_->hasDerivedData<VolumeMinMax>() && volume_->getDerivedData<VolumeMinMax>()->getNumChannels() > channel_) { //< if volume min/max values already computed, use them float min = rwm.normalizedToRealWorld(volume_->getDerivedData<VolumeMinMax>()->getMinNormalized(channel_)); float max = rwm.normalizedToRealWorld(volume_->getDerivedData<VolumeMinMax>()->getMaxNormalized(channel_)); tfi->setDomain(tgt::vec2(min, max)); fitToDomainPending_ = false; } else { // if min/max values not available, compute them asynchronously // and fit to full normalized range in the mean time volume_->getDerivedDataThreaded<VolumeMinMax>(); fitToDomainPending_ = true; float min = rwm.normalizedToRealWorld(0.f); float max = rwm.normalizedToRealWorld(1.f); tfi->setDomain(tgt::vec2(min, max)); } invalidate(); } }
void setUniform(tgt::Shader* shader, const std::string& volumeUniform, const std::string& structUniform, const VolumeBase* vh, const tgt::TextureUnit* texUnit, const tgt::Camera* camera, const tgt::vec4& lightPosition) { if(texUnit) shader->setUniform(volumeUniform, texUnit->getUnitNumber()); // volume size, i.e. dimensions of the proxy geometry in world coordinates shader->setUniform(structUniform + ".datasetDimensions_", tgt::vec3(vh->getDimensions())); shader->setUniform(structUniform + ".datasetDimensionsRCP_", vec3(1.f) / tgt::vec3(vh->getDimensions())); // volume spacing, i.e. voxel size shader->setUniform(structUniform + ".datasetSpacing_", vh->getSpacing()); shader->setUniform(structUniform + ".datasetSpacingRCP_", vec3(1.f) / vh->getSpacing()); // volume's size in its physical coordinates shader->setUniform(structUniform + ".volumeCubeSize_", vh->getCubeSize()); shader->setUniform(structUniform + ".volumeCubeSizeRCP_", vec3(1.f) / vh->getCubeSize()); shader->setUniform(structUniform + ".volumeOffset_", vh->getOffset()); shader->setUniform(structUniform + ".numChannels_", static_cast<GLint>(vh->getNumChannels())); // volume's transformation matrix shader->setUniform(structUniform + ".physicalToWorldMatrix_", vh->getPhysicalToWorldMatrix()); tgt::mat4 invTm = vh->getWorldToPhysicalMatrix(); shader->setUniform(structUniform + ".worldToPhysicalMatrix_", invTm); shader->setUniform(structUniform + ".worldToTextureMatrix_", vh->getWorldToTextureMatrix()); shader->setUniform(structUniform + ".textureToWorldMatrix_", vh->getTextureToWorldMatrix()); // camera position in volume object coords if (camera) shader->setUniform(structUniform + ".cameraPositionPhysical_", invTm*camera->getPosition()); // light position in volume object coords shader->setUniform(structUniform + ".lightPositionPhysical_", (invTm*lightPosition).xyz()); LGL_ERROR; // bit depth of the volume shader->setUniform(structUniform + ".bitDepth_", (GLint)(vh->getBytesPerVoxel() * 8)); // construct shader real-world mapping by combining volume rwm and pixel transfer mapping RealWorldMapping rwm = vh->getRealWorldMapping(); RealWorldMapping transferMapping; if (vh->getRepresentation<VolumeGL>()) transferMapping = vh->getRepresentation<VolumeGL>()->getPixelTransferMapping(); else LWARNINGC("voreen.glsl", "setUniform(): no VolumeGL"); RealWorldMapping shaderMapping = RealWorldMapping::combine(transferMapping.getInverseMapping(), rwm); shader->setUniform(structUniform + ".rwmScale_", shaderMapping.getScale()); shader->setUniform(structUniform + ".rwmOffset_", shaderMapping.getOffset()); }
//---------------------------------------------------------------------------------------------- // other functions //---------------------------------------------------------------------------------------------- void TransFunc1DKeysEditor::checkDomainVersusData() { bool warnLower = false; bool warnUpper = false; if (transferFuncIntensity_ && volume_ /* && volume_->hasRepresentation<VolumeRAM>() */) { if (volume_->hasDerivedData<VolumeMinMax>()) { // if min/max already present, use them //calculate Min/Max values: float min = volume_->getDerivedData<VolumeMinMax>()->getMinNormalized(); float max = volume_->getDerivedData<VolumeMinMax>()->getMaxNormalized(); RealWorldMapping rwm = volume_->getRealWorldMapping(); min = rwm.normalizedToRealWorld(min); max = rwm.normalizedToRealWorld(max); tgt::vec2 domain = transferFuncIntensity_->getDomain(); float avg = (domain.x + domain.y) / 2.0f; if(domain.x > min) warnLower = true; if(domain.y < max) warnUpper = true; if(min > avg) warnLower = true; if(max < avg) warnUpper = true; } else { // otherwise compute min/max values in background volume_->getDerivedDataThreaded<VolumeMinMax>(); } } QPalette lowerPal(lowerMappingSpin_->palette()); if(warnLower) lowerPal.setColor(QPalette::Base, Qt::yellow); else lowerPal.setColor(QPalette::Base, QApplication::palette().color(QPalette::Base)); lowerMappingSpin_->setPalette(lowerPal); QPalette upperPal(upperMappingSpin_->palette()); if(warnUpper) upperPal.setColor(QPalette::Base, Qt::yellow); else upperPal.setColor(QPalette::Base, QApplication::palette().color(QPalette::Base)); upperMappingSpin_->setPalette(upperPal); }
void PointCloud :: VolumeFill(const Volume* vol, double min) { const VolumeRAM* volRam = vol->getRepresentation<VolumeRAM>(); RealWorldMapping rwm = vol->getRealWorldMapping(); SetOrientation(vol->getVoxelToWorldMatrix()); tgt::svec3 dims = vol->getDimensions(); tgt::dvec4 pworld; double valNorm; double valRW; int non_zero = 0; total_weight = 0; entries_num = dims.x*dims.y*dims.z; points = new tgt::vec3[entries_num+1]; values = new double[entries_num+1]; max_value = 0; min_value = min; for (int i=0; i<dims.x; ++i) for (int j=0; j<dims.y; ++j) for (int k=0; k<dims.z; ++k) { valNorm = volRam->getVoxelNormalizedLinear(tgt::dvec3(0.5+i, 0.5+j, 0.5+k)); valRW = rwm.normalizedToRealWorld(valNorm); if (fabs(valRW)>min_value) { pworld = vol->getVoxelToWorldMatrix() * (tgt::dvec4(0.5+i, 0.5+j, 0.5+k, 1.0)); points[non_zero][0] = pworld.x; points[non_zero][1] = pworld.y; points[non_zero][2] = pworld.z; values[non_zero] = valRW; if (fabs(valRW)>max_value) { max_value = fabs(valRW); } total_weight += valRW; non_zero++; } } entries_num = non_zero; have_points = true; }
void setUniform(tgt::Shader* shader, const std::string& imageUniform, const std::string& structUniform, const Slice* sl, const tgt::TextureUnit* texUnit) { bool ignoreErr = shader->getIgnoreUniformLocationError(); shader->setIgnoreUniformLocationError(true); if(texUnit) shader->setUniform(imageUniform, texUnit->getUnitNumber()); // volume size, i.e. dimensions of the proxy geometry in world coordinates shader->setUniform(structUniform + ".datasetDimensions_", tgt::vec3(sl->getTexture()->getDimensions())); shader->setUniform(structUniform + ".datasetDimensionsRCP_", vec3(1.f) / tgt::vec3(sl->getTexture()->getDimensions())); // volume spacing, i.e. voxel size //shader->setUniform(structUniform + ".datasetSpacing_", sl->getSpacing()); //shader->setUniform(structUniform + ".datasetSpacingRCP_", vec3(1.f) / sl->getSpacing()); shader->setUniform(structUniform + ".numChannels_", static_cast<GLint>(sl->getTexture()->getNumChannels())); //shader->setUniform(structUniform + ".numChannels_", static_cast<GLint>(1)); // volume's transformation matrix //shader->setUniform(structUniform + ".physicalToWorldMatrix_", sl->getPhysicalToWorldMatrix()); //tgt::mat4 invTm = sl->getWorldToPhysicalMatrix(); //shader->setUniform(structUniform + ".worldToPhysicalMatrix_", invTm); shader->setUniform(structUniform + ".worldToTextureMatrix_", sl->getWorldToTextureMatrix()); shader->setUniform(structUniform + ".textureToWorldMatrix_", sl->getTextureToWorldMatrix()); LGL_ERROR; // construct shader real-world mapping by combining volume rwm and pixel transfer mapping RealWorldMapping rwm = sl->getRealWorldMapping(); //RealWorldMapping transferMapping; //if (sl->getRepresentation<VolumeGL>()) //transferMapping = sl->getRepresentation<VolumeGL>()->getPixelTransferMapping(); //else //LWARNINGC("voreen.glsl", "setUniform(): no VolumeGL"); //RealWorldMapping shaderMapping = RealWorldMapping::combine(transferMapping.getInverseMapping(), rwm); RealWorldMapping shaderMapping = rwm; shader->setUniform(structUniform + ".rwmScale_", shaderMapping.getScale()); shader->setUniform(structUniform + ".rwmOffset_", shaderMapping.getOffset()); shader->setIgnoreUniformLocationError(ignoreErr); }
Histogram1D createHistogram1DFromVolume(const VolumeBase* handle, int bucketCount) { const VolumeRAM* vol = handle->getRepresentation<VolumeRAM>(); RealWorldMapping rwm = handle->getRealWorldMapping(); float min = handle->getDerivedData<VolumeMinMax>()->getMinNormalized(); float max = handle->getDerivedData<VolumeMinMax>()->getMaxNormalized(); min = rwm.normalizedToRealWorld(min); max = rwm.normalizedToRealWorld(max); Histogram1D h(min, max, bucketCount); for(size_t i=0; i<vol->getNumVoxels(); i++) { float v = vol->getVoxelNormalized(i); v = rwm.normalizedToRealWorld(v); h.addSample(v); } return h; }
void TransFunc1DKeysEditor::volumeChanged() { if (volume_ /*&& volume_->hasRepresentation<VolumeRAM>()*/) { updateDataBounds(); /*if(unit == "") dataLabel_->setText("Data Bounds"); else dataLabel_->setText(QString("Data Bounds [") + QString::fromStdString(unit) + "]");*/ RealWorldMapping rwm = volume_->getRealWorldMapping(); if(property_->getAlwaysFitToDomain() || (((rwm.getOffset() != 0.0f) || (rwm.getScale() != 1.0f) || (rwm.getUnit() != "")) && *transferFuncIntensity_ == TransFunc1DKeys())) { fitDomainToData(); } // propagate new volume to transfuncMappingCanvas transCanvas_->volumeChanged(volume_); } else { transCanvas_->volumeChanged(0); } checkDomainVersusData(); }
void TransFunc1DKeysEditor::updateDataBounds() { if (!volume_) return; //calculate Min/Max values: float min = 0.f; float max = 1.f; if (volume_->hasDerivedData<VolumeMinMax>()) { min = volume_->getDerivedData<VolumeMinMax>()->getMinNormalized(); max = volume_->getDerivedData<VolumeMinMax>()->getMaxNormalized(); } else { volume_->getDerivedDataThreaded<VolumeMinMax>(); } RealWorldMapping rwm = volume_->getRealWorldMapping(); min = rwm.normalizedToRealWorld(min); max = rwm.normalizedToRealWorld(max); //std::string unit = rwm.getUnit(); lowerData_->setText(QString::number(min)); upperData_->setText(QString::number(max)); }
Histogram1D createHistogram1DFromVolume(const VolumeBase* handle, int bucketCount, size_t channel /*= 0*/) { RealWorldMapping rwm = handle->getRealWorldMapping(); const VolumeMinMax* volumeMinMax = handle->getDerivedData<VolumeMinMax>(); tgtAssert(channel < volumeMinMax->getNumChannels(), "invalid channel"); float min = volumeMinMax->getMinNormalized(channel); float max = volumeMinMax->getMaxNormalized(channel); min = rwm.normalizedToRealWorld(min); max = rwm.normalizedToRealWorld(max); Histogram1D h(min, max, bucketCount); // prefer RAM over disk representation, but only if RAM volume is already present const VolumeRAM* volumeRam = 0; const VolumeDisk* volumeDisk = 0; if (handle->hasRepresentation<VolumeRAM>()) volumeRam = handle->getRepresentation<VolumeRAM>(); else if (handle->hasRepresentation<VolumeDisk>()) volumeDisk = handle->getRepresentation<VolumeDisk>(); else { LWARNINGC("voreen.Histogram", "Unable to compute 1D histogram: neither disk nor ram represenation available"); return h; } tgtAssert(volumeRam || volumeDisk, "no representation"); // iterate over slices tgt::svec3 dims = handle->getDimensions(); tgt::svec3 pos; for (pos.z = 0; pos.z < dims.z; ++pos.z) { try { boost::this_thread::sleep(boost::posix_time::seconds(0)); } catch(boost::thread_interrupted&) { throw boost::thread_interrupted(); } if (volumeRam) { // access volume data in RAM directly for (pos.y = 0; pos.y < dims.y; ++pos.y) { for (pos.x = 0; pos.x < dims.x; ++pos.x) { float val = volumeRam->getVoxelNormalized(pos, channel); val = rwm.normalizedToRealWorld(val); h.addSample(val); } } } else if (volumeDisk) { try { // temporarily load current slice into RAM VolumeRAM* sliceVolume = volumeDisk->loadSlices(pos.z, pos.z); tgtAssert(sliceVolume, "null pointer returned (exception expected)"); for (pos.y = 0; pos.y < dims.y; ++pos.y) { for (pos.x = 0; pos.x < dims.x; ++pos.x) { float val = sliceVolume->getVoxelNormalized(tgt::svec3(pos.x, pos.y, 0), channel); val = rwm.normalizedToRealWorld(val); h.addSample(val); } } delete sliceVolume; } catch (tgt::Exception& e) { LWARNINGC("voreen.Histogram", "Unable to compute 1D histogram: failed to load slice from disk volume: " + std::string(e.what())); return h; } } else { tgtAssert(false, "should never get here"); } } return h; }
Histogram2D createHistogram2DFromVolume(const VolumeBase* handle, int bucketCountIntensity, int bucketCountGradient) { const VolumeRAM* vol = handle->getRepresentation<VolumeRAM>(); RealWorldMapping rwm = handle->getRealWorldMapping(); ivec3 dims = vol->getDimensions(); vec3 sp = handle->getSpacing(); float min = handle->getDerivedData<VolumeMinMax>()->getMinNormalized(); float max = handle->getDerivedData<VolumeMinMax>()->getMaxNormalized(); min = rwm.normalizedToRealWorld(min); max = rwm.normalizedToRealWorld(max); float minGradLength = 0.0f; // always 0 float maxGradLength = 0.0f; //TODO: improve performance ivec3 pos; for (pos.z = 0; pos.z < dims.z; ++pos.z) { try { boost::this_thread::sleep(boost::posix_time::seconds(0)); } catch(boost::thread_interrupted&) { throw boost::thread_interrupted(); } for (pos.y = 0; pos.y < dims.y; ++pos.y) { for (pos.x = 0; pos.x < dims.x; ++pos.x) { //vec3 grad = VolumeOperatorGradient::calcGradientCentralDifferences(vol, sp, pos); vec3 grad = VolumeOperatorGradient::calcGradientSobel(vol, sp, pos); float nlength = tgt::length(grad) * rwm.getScale(); if (nlength > maxGradLength) maxGradLength = nlength; } } } Histogram2D h(min, max, bucketCountIntensity, minGradLength, maxGradLength, bucketCountGradient); for (pos.z = 0; pos.z < dims.z; ++pos.z) { try { boost::this_thread::sleep(boost::posix_time::seconds(0)); } catch(boost::thread_interrupted&) { throw boost::thread_interrupted(); } for (pos.y = 0; pos.y < dims.y; ++pos.y) { for (pos.x = 0; pos.x < dims.x; ++pos.x) { //vec3 grad = VolumeOperatorGradient::calcGradientCentralDifferences(vol, sp, pos); vec3 grad = VolumeOperatorGradient::calcGradientSobel(vol, sp, pos); float nlength = tgt::length(grad) * rwm.getScale(); float v = vol->getVoxelNormalized(pos); v = rwm.normalizedToRealWorld(v); h.addSample(v, nlength); } } } return h; }
void VolumeMasking::maskVolume() { tgtAssert(inport_.hasData(), "Inport has not data"); forceUpdate_ = false; const VolumeRAM* vol = inport_.getData()->getRepresentation<VolumeRAM>(); if (vol) { VolumeRAM* v = 0; v = vol->clone(); tgt::Texture* maskTexture = maskFunction_.get()->getTexture(); TransFunc1DKeys* tf = dynamic_cast<TransFunc1DKeys*>(maskFunction_.get()); maskTexture->downloadTexture(); const int maskTexDim = maskTexture->getDimensions().x; RealWorldMapping rwm = inport_.getData()->getRealWorldMapping(); // apply masking if (passedVoxelAction_.isSelected("maxIntensity")) { for (size_t i=0; i<v->getNumVoxels(); i++) { float intensity = vol->getVoxelNormalized(i); intensity = rwm.normalizedToRealWorld(intensity); intensity = tf->realWorldToNormalized(intensity); int index = static_cast<int>(intensity*(maskTexDim-1)); index = tgt::clamp(index, 0, maskTexDim-1); int alpha = maskTexture->texel< tgt::Vector4<uint8_t> >(static_cast<size_t>(index)).a; v->setVoxelNormalized(alpha == 0 ? 0.f : 1.f, i); //progressBar_->setProgress(static_cast<float>(i) / static_cast<float>(v->getNumVoxels())); } } else if (passedVoxelAction_.isSelected("passThrough")) { for (size_t i=0; i<v->getNumVoxels(); i++) { float intensity = vol->getVoxelNormalized(i); intensity = rwm.normalizedToRealWorld(intensity); intensity = tf->realWorldToNormalized(intensity); int index = static_cast<int>(intensity*(maskTexDim-1)); index = tgt::clamp(index, 0, maskTexDim-1); int alpha = maskTexture->texel< tgt::Vector4<uint8_t> >(static_cast<size_t>(index)).a; if (alpha == 0) v->setVoxelNormalized(0.f, i); } } else if (passedVoxelAction_.isSelected("alpha")) { for (size_t i=0; i<v->getNumVoxels(); i++) { float intensity = vol->getVoxelNormalized(i); intensity = rwm.normalizedToRealWorld(intensity); intensity = tf->realWorldToNormalized(intensity); int index = static_cast<int>(intensity*(maskTexDim-1)); index = tgt::clamp(index, 0, maskTexDim-1); int alpha = maskTexture->texel< tgt::Vector4<uint8_t> >(static_cast<size_t>(index)).a; v->setVoxelNormalized((float)alpha / 255.0f, i); } } else { LWARNING("Unknown voxel action: " << passedVoxelAction_.get()); } Volume* vh = new Volume(v, inport_.getData()); if (passedVoxelAction_.isSelected("alpha")) vh->setRealWorldMapping(RealWorldMapping()); outport_.setData(vh); } else { outport_.setData(0); } }