diff --git a/Modules/VtkShaders/mitkVtkShaderRepository.cpp b/Modules/VtkShaders/mitkVtkShaderRepository.cpp index fab7320c52..08804b53f5 100644 --- a/Modules/VtkShaders/mitkVtkShaderRepository.cpp +++ b/Modules/VtkShaders/mitkVtkShaderRepository.cpp @@ -1,588 +1,635 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #define SR_INFO MITK_INFO("shader.repository") #define SR_WARN MITK_WARN("shader.repository") #define SR_ERROR MITK_ERROR("shader.repository") #include "mitkVtkShaderRepository.h" #include "mitkVtkShaderProgram.h" #include "mitkShaderProperty.h" #include "mitkProperties.h" #include "mitkDataNode.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int mitk::VtkShaderRepository::shaderId = 0; const bool mitk::VtkShaderRepository::debug = false; mitk::VtkShaderRepository::VtkShaderRepository() { LoadShaders(); } mitk::VtkShaderRepository::~VtkShaderRepository() { } mitk::IShaderRepository::ShaderProgram::Pointer mitk::VtkShaderRepository::CreateShaderProgram() { mitk::IShaderRepository::ShaderProgram::Pointer shaderProg = (mitk::VtkShaderProgram::New()).GetPointer(); return shaderProg; } void mitk::VtkShaderRepository::LoadShaders() { itk::Directory::Pointer dir = itk::Directory::New(); std::string dirPath = "./vtk_shader"; if( dir->Load( dirPath.c_str() ) ) { int n = dir->GetNumberOfFiles(); for(int r=0;rGetFile( r ); std::string extension = itksys::SystemTools::GetFilenameExtension(filename); if(extension.compare(".xml")==0) { Shader::Pointer element=Shader::New(); element->SetName(itksys::SystemTools::GetFilenameWithoutExtension(filename)); std::string filePath = dirPath + std::string("/") + element->GetName() + std::string(".xml"); SR_INFO(debug) << "found shader '" << element->GetName() << "'"; std::ifstream fileStream(filePath.c_str()); element->LoadXmlShader(fileStream); shaders.push_back(element); } } } } mitk::VtkShaderRepository::Shader::Pointer mitk::VtkShaderRepository::GetShaderImpl(const std::string &name) const { std::list::const_iterator i = shaders.begin(); while( i != shaders.end() ) { if( (*i)->GetName() == name) return (*i); i++; } return Shader::Pointer(); } int mitk::VtkShaderRepository::LoadShader(std::istream& stream, const std::string& filename) { Shader::Pointer element=Shader::New(); element->SetName(filename); element->SetId(shaderId++); element->LoadXmlShader(stream); shaders.push_back(element); SR_INFO(debug) << "found shader '" << element->GetName() << "'"; return element->GetId(); } bool mitk::VtkShaderRepository::UnloadShader(int id) { for (std::list::iterator i = shaders.begin(); i != shaders.end(); ++i) { if ((*i)->GetId() == id) { shaders.erase(i); return true; } } return false; } mitk::VtkShaderRepository::Shader::Shader() { } mitk::VtkShaderRepository::Shader::~Shader() { } void mitk::VtkShaderRepository::Shader::SetVertexShaderCode(const std::string& code) { this->m_VertexShaderCode = code; } std::string mitk::VtkShaderRepository::Shader::GetVertexShaderCode() const { return this->m_VertexShaderCode; } void mitk::VtkShaderRepository::Shader::SetFragmentShaderCode(const std::string& code) { this->m_FragmentShaderCode = code; } std::string mitk::VtkShaderRepository::Shader::GetFragmentShaderCode() const { return this->m_FragmentShaderCode; } +void mitk::VtkShaderRepository::Shader::SetGeometryShaderCode(const std::string& code) +{ + this->m_GeometryShaderCode = code; +} + +std::string mitk::VtkShaderRepository::Shader::GetGeometryShaderCode() const +{ + return this->m_GeometryShaderCode; +} + std::list mitk::VtkShaderRepository::Shader::GetUniforms() const { return uniforms; } void mitk::VtkShaderRepository::Shader::LoadXmlShader(std::istream& stream) { std::string content; content.reserve(2048); char buffer[2048]; while (stream.read(buffer, sizeof(buffer))) { content.append(buffer, sizeof(buffer)); } content.append(buffer, static_cast(stream.gcount())); if (content.empty()) return; this->SetMaterialXml(content); vtkXMLMaterialParser* parser = vtkXMLMaterialParser::New(); vtkXMLMaterial* material = vtkXMLMaterial::New(); parser->SetMaterial(material); parser->Parse(content.c_str()); parser->Delete(); if (material == NULL) return; // Vertexshader uniforms { vtkXMLShader *s=material->GetVertexShader(); if (s) { SetVertexShaderCode(s->GetCode()); vtkXMLDataElement *x=s->GetRootElement(); int n=x->GetNumberOfNestedElements(); for(int r=0;rGetNestedElement(r); if(strcmp(y->GetName(),"ApplicationUniform") == 0 || strcmp(y->GetName(), "Uniform") == 0) { Uniform::Pointer element=Uniform::New(); element->LoadFromXML(y); uniforms.push_back(element); } } } } // Fragmentshader uniforms { vtkXMLShader *s=material->GetFragmentShader(); if (s) { SetFragmentShaderCode(s->GetCode()); vtkXMLDataElement *x=s->GetRootElement(); int n=x->GetNumberOfNestedElements(); for(int r=0;rGetNestedElement(r); if(strcmp(y->GetName(),"ApplicationUniform") == 0 || strcmp(y->GetName(), "Uniform") == 0) { Uniform::Pointer element=Uniform::New(); element->LoadFromXML(y); uniforms.push_back(element); } } } } + + // Geometryshader uniforms + { + vtkXMLShader *s=material->GetGeometryShader(); + if (s) + { + SetGeometryShaderCode(s->GetCode()); + vtkXMLDataElement *x=s->GetRootElement(); + int n=x->GetNumberOfNestedElements(); + for(int r=0;rGetNestedElement(r); + if(strcmp(y->GetName(),"ApplicationUniform") == 0 || + strcmp(y->GetName(), "Uniform") == 0) + { + Uniform::Pointer element=Uniform::New(); + element->LoadFromXML(y); + uniforms.push_back(element); + } + } + } + } material->Delete(); } mitk::VtkShaderRepository::Shader::Uniform::Uniform() { } mitk::VtkShaderRepository::Shader::Uniform::~Uniform() { } void mitk::VtkShaderRepository::Shader::Uniform::LoadFromXML(vtkXMLDataElement *y) { //MITK_INFO << "found uniform '" << y->GetAttribute("name") << "' type=" << y->GetAttribute("type");// << " default=" << y->GetAttribute("value"); name = y->GetAttribute("name"); const char *sType=y->GetAttribute("type"); if(!strcmp(sType,"float")) type=glsl_float; else if(!strcmp(sType,"vec2")) type=glsl_vec2; else if(!strcmp(sType,"vec3")) type=glsl_vec3; else if(!strcmp(sType,"vec4")) type=glsl_vec4; else if(!strcmp(sType,"int")) type=glsl_int; else if(!strcmp(sType,"ivec2")) type=glsl_ivec2; else if(!strcmp(sType,"ivec3")) type=glsl_ivec3; else if(!strcmp(sType,"ivec4")) type=glsl_ivec4; else { type=glsl_none; SR_WARN << "unknown type for uniform '" << name << "'" ; } defaultFloat[0]=defaultFloat[1]=defaultFloat[2]=defaultFloat[3]=0; const char *sDefault=y->GetAttribute("value"); if(sDefault) { switch(type) { case glsl_float: sscanf(sDefault,"%f",&defaultFloat[0]); break; case glsl_vec2: sscanf(sDefault,"%f %f",&defaultFloat[0],&defaultFloat[1]); break; case glsl_vec3: sscanf(sDefault,"%f %f %f",&defaultFloat[0],&defaultFloat[1],&defaultFloat[2]); break; case glsl_vec4: sscanf(sDefault,"%f %f %f %f",&defaultFloat[0],&defaultFloat[1],&defaultFloat[2],&defaultFloat[3]); break; case glsl_int: sscanf(sDefault,"%d",&defaultInt[0]); break; case glsl_ivec2: sscanf(sDefault,"%d %d",&defaultInt[0],&defaultInt[1]); break; case glsl_ivec3: sscanf(sDefault,"%d %d %d",&defaultInt[0],&defaultInt[1],&defaultInt[2]); break; case glsl_ivec4: sscanf(sDefault,"%d %d %d %d",&defaultInt[0],&defaultInt[1],&defaultInt[2],&defaultInt[3]); break; case glsl_none: break; } } } void mitk::VtkShaderRepository::AddDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) const { node->AddProperty( "shader", mitk::ShaderProperty::New(), renderer, overwrite ); std::list::const_iterator i = shaders.begin(); while( i != shaders.end() ) { std::list uniforms = (*i)->GetUniforms(); std::string shaderName = (*i)->GetName(); std::list::const_iterator j = uniforms.begin(); while( j != uniforms.end() ) { std::string propertyName = "shader." + shaderName + "." + (*j)->name; switch( (*j)->type ) { case Shader::Uniform::glsl_float: node->AddProperty( propertyName.c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite ); break; case Shader::Uniform::glsl_vec2: node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite ); node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite ); break; case Shader::Uniform::glsl_vec3: node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite ); node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite ); node->AddProperty( (propertyName+".z").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[2] ), renderer, overwrite ); break; case Shader::Uniform::glsl_vec4: node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite ); node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite ); node->AddProperty( (propertyName+".z").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[2] ), renderer, overwrite ); node->AddProperty( (propertyName+".w").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[3] ), renderer, overwrite ); break; case Shader::Uniform::glsl_int: node->AddProperty( propertyName.c_str(), mitk::IntProperty::New( (*j)->defaultInt[0] ), renderer, overwrite ); break; case Shader::Uniform::glsl_ivec2: node->AddProperty( (propertyName+".x").c_str(), mitk::IntProperty::New( (*j)->defaultInt[0] ), renderer, overwrite ); node->AddProperty( (propertyName+".y").c_str(), mitk::IntProperty::New( (*j)->defaultInt[1] ), renderer, overwrite ); break; case Shader::Uniform::glsl_ivec3: node->AddProperty( (propertyName+".x").c_str(), mitk::IntProperty::New( (*j)->defaultInt[0] ), renderer, overwrite ); node->AddProperty( (propertyName+".y").c_str(), mitk::IntProperty::New( (*j)->defaultInt[1] ), renderer, overwrite ); node->AddProperty( (propertyName+".z").c_str(), mitk::IntProperty::New( (*j)->defaultInt[2] ), renderer, overwrite ); break; case Shader::Uniform::glsl_ivec4: node->AddProperty( (propertyName+".x").c_str(), mitk::IntProperty::New( (*j)->defaultInt[0] ), renderer, overwrite ); node->AddProperty( (propertyName+".y").c_str(), mitk::IntProperty::New( (*j)->defaultInt[1] ), renderer, overwrite ); node->AddProperty( (propertyName+".z").c_str(), mitk::IntProperty::New( (*j)->defaultInt[2] ), renderer, overwrite ); node->AddProperty( (propertyName+".w").c_str(), mitk::IntProperty::New( (*j)->defaultInt[3] ), renderer, overwrite ); break; case Shader::Uniform::glsl_none: break; } j++; } i++; } } std::list mitk::VtkShaderRepository::GetShaders() const { std::list result; for (std::list::const_iterator i = shaders.begin(); i != shaders.end(); ++i) { result.push_back(i->GetPointer()); } return result; } mitk::IShaderRepository::Shader::Pointer mitk::VtkShaderRepository::GetShader(const std::string& name) const { for (std::list::const_iterator i = shaders.begin(); i != shaders.end(); ++i) { if ((*i)->GetName() == name) return i->GetPointer(); } return IShaderRepository::Shader::Pointer(); } mitk::IShaderRepository::Shader::Pointer mitk::VtkShaderRepository::GetShader(int id) const { for (std::list::const_iterator i = shaders.begin(); i != shaders.end(); ++i) { if ((*i)->GetId() == id) return i->GetPointer(); } return IShaderRepository::Shader::Pointer(); } void mitk::VtkShaderRepository::UpdateShaderProgram(ShaderProgram* shaderProgram, DataNode* node, BaseRenderer* renderer) const { VtkShaderProgram* mitkVtkShaderProgram = dynamic_cast(shaderProgram); mitk::ShaderProperty *sep= dynamic_cast(node->GetProperty("shader",renderer)); if(!sep) { mitkVtkShaderProgram->SetVtkShaderProgram(0); return; } Shader::Pointer s = GetShaderImpl(sep->GetValueAsString()); // Need update pipeline mode if(sep->GetMTime() > mitkVtkShaderProgram->GetShaderTimestampUpdate().GetMTime()) { if( s.IsNull() ) { mitkVtkShaderProgram->SetVtkShaderProgram(0); MITK_INFO << "disabling shader"; mitkVtkShaderProgram->GetShaderTimestampUpdate().Modified(); return; } vtkSmartPointer program = vtkSmartPointer::New(); #if ((VTK_MAJOR_VERSION < 6 ) || ((VTK_MAJOR_VERSION == 6) && (VTK_MINOR_VERSION == 0) )) program->SetContext(dynamic_cast(renderer->GetRenderWindow())); #else program->SetContext(renderer->GetRenderWindow()); #endif // The vertext shader vtkShader2 *shader = vtkShader2::New(); shader->SetType(VTK_SHADER_TYPE_VERTEX); shader->SetSourceCode(s->GetVertexShaderCode().c_str()); #if ((VTK_MAJOR_VERSION < 6 ) || ((VTK_MAJOR_VERSION == 6) && (VTK_MINOR_VERSION == 0) )) shader->SetContext(dynamic_cast(renderer->GetRenderWindow())); #else shader->SetContext(renderer->GetRenderWindow()); #endif program->GetShaders()->AddItem(shader); shader->Delete(); // The fragment shader shader = vtkShader2::New(); shader->SetType(VTK_SHADER_TYPE_FRAGMENT); shader->SetSourceCode(s->GetFragmentShaderCode().c_str()); #if ((VTK_MAJOR_VERSION < 6 ) || ((VTK_MAJOR_VERSION == 6) && (VTK_MINOR_VERSION == 0) )) shader->SetContext(dynamic_cast(renderer->GetRenderWindow())); #else shader->SetContext(renderer->GetRenderWindow()); #endif program->GetShaders()->AddItem(shader); shader->Delete(); + if(s->GetGeometryShaderCode().size()>0) + { + // The Geometry shader + shader = vtkShader2::New(); + shader->SetType(VTK_SHADER_TYPE_GEOMETRY); + shader->SetSourceCode(s->GetGeometryShaderCode().c_str()); +#if ((VTK_MAJOR_VERSION < 6 ) || ((VTK_MAJOR_VERSION == 6) && (VTK_MINOR_VERSION == 0) )) + shader->SetContext(dynamic_cast(renderer->GetRenderWindow())); +#else + shader->SetContext(renderer->GetRenderWindow()); +#endif + program->GetShaders()->AddItem(shader); + shader->Delete(); + } + program->Build(); mitkVtkShaderProgram->SetVtkShaderProgram(program); mitkVtkShaderProgram->GetShaderTimestampUpdate().Modified(); } if(s.IsNull()) return; // update uniforms vtkShaderProgram2 *p = mitkVtkShaderProgram->GetVtkShaderProgram(); if(!p) return; std::list::const_iterator j = s->uniforms.begin(); while( j != s->uniforms.end() ) { std::string propertyName = "shader." + s->GetName() + "." + (*j)->name; // MITK_INFO << "querying property: " << propertyName; // mitk::BaseProperty *p = node->GetProperty( propertyName.c_str(), renderer ); // if( p && p->GetMTime() > MTime.GetMTime() ) { float fval[4]; int ival[4]; // MITK_INFO << "copying property " << propertyName << " ->->- " << (*j)->name << " type=" << (*j)->type ; switch( (*j)->type ) { case Shader::Uniform::glsl_float: node->GetFloatProperty( propertyName.c_str(), fval[0], renderer ); p->GetUniformVariables()->SetUniformf((*j)->name.c_str(), 1, fval); break; case Shader::Uniform::glsl_vec2: node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer ); node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer ); p->GetUniformVariables()->SetUniformf((*j)->name.c_str(), 2, fval); break; case Shader::Uniform::glsl_vec3: node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer ); node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer ); node->GetFloatProperty( (propertyName+".z").c_str(), fval[2], renderer ); //p->SetUniform3f( (*j)->name.c_str(), fval ); p->GetUniformVariables()->SetUniformf((*j)->name.c_str(), 3, fval); break; case Shader::Uniform::glsl_vec4: node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer ); node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer ); node->GetFloatProperty( (propertyName+".z").c_str(), fval[2], renderer ); node->GetFloatProperty( (propertyName+".w").c_str(), fval[3], renderer ); p->GetUniformVariables()->SetUniformf((*j)->name.c_str(), 4, fval); break; case Shader::Uniform::glsl_int: node->GetIntProperty( propertyName.c_str(), ival[0], renderer ); p->GetUniformVariables()->SetUniformi((*j)->name.c_str(), 1, ival); break; case Shader::Uniform::glsl_ivec2: node->GetIntProperty( (propertyName+".x").c_str(), ival[0], renderer ); node->GetIntProperty( (propertyName+".y").c_str(), ival[1], renderer ); p->GetUniformVariables()->SetUniformi((*j)->name.c_str(), 2, ival); break; case Shader::Uniform::glsl_ivec3: node->GetIntProperty( (propertyName+".x").c_str(), ival[0], renderer ); node->GetIntProperty( (propertyName+".y").c_str(), ival[1], renderer ); node->GetIntProperty( (propertyName+".z").c_str(), ival[2], renderer ); //p->SetUniform3f( (*j)->name.c_str(), fval ); p->GetUniformVariables()->SetUniformi((*j)->name.c_str(), 3, ival); break; case Shader::Uniform::glsl_ivec4: node->GetIntProperty( (propertyName+".x").c_str(), ival[0], renderer ); node->GetIntProperty( (propertyName+".y").c_str(), ival[1], renderer ); node->GetIntProperty( (propertyName+".z").c_str(), ival[2], renderer ); node->GetIntProperty( (propertyName+".w").c_str(), ival[3], renderer ); p->GetUniformVariables()->SetUniformi((*j)->name.c_str(), 4, ival); break; case Shader::Uniform::glsl_none: break; } } j++; } return; } diff --git a/Modules/VtkShaders/mitkVtkShaderRepository.h b/Modules/VtkShaders/mitkVtkShaderRepository.h index e1c8f33407..a8ac7f456c 100644 --- a/Modules/VtkShaders/mitkVtkShaderRepository.h +++ b/Modules/VtkShaders/mitkVtkShaderRepository.h @@ -1,171 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITKVTKSHADERREPOSITORY_H_ #define _MITKVTKSHADERREPOSITORY_H_ #include "mitkIShaderRepository.h" #include #include class vtkXMLDataElement; class vtkXMLMaterial; class vtkProperty; namespace mitk { /** * \brief Management class for vtkShader XML descriptions. * * Looks for all XML shader files in a given directory and adds default properties * for each shader object (shader uniforms) to the specified mitk::DataNode. * * Additionally, it provides a utility function for applying properties for shaders * in mappers. */ class VtkShaderRepository : public IShaderRepository { protected: class Shader : public IShaderRepository::Shader { public: mitkClassMacro( Shader, itk::Object ) itkFactorylessNewMacro( Self ) class Uniform : public itk::Object { public: mitkClassMacro( Uniform, itk::Object ) itkFactorylessNewMacro( Self ) enum Type { glsl_none, glsl_float, glsl_vec2, glsl_vec3, glsl_vec4, glsl_int, glsl_ivec2, glsl_ivec3, glsl_ivec4 }; /** * Constructor */ Uniform(); /** * Destructor */ ~Uniform(); Type type; std::string name; int defaultInt[4]; float defaultFloat[4]; void LoadFromXML(vtkXMLDataElement *e); }; std::list uniforms; /** * Constructor */ Shader(); /** * Destructor */ ~Shader(); void SetVertexShaderCode(const std::string& code); std::string GetVertexShaderCode() const; void SetFragmentShaderCode(const std::string& code); std::string GetFragmentShaderCode() const; + void SetGeometryShaderCode(const std::string& code); + std::string GetGeometryShaderCode() const; + std::list GetUniforms() const; private: friend class VtkShaderRepository; std::string m_VertexShaderCode; std::string m_FragmentShaderCode; + std::string m_GeometryShaderCode; void LoadXmlShader(std::istream& stream); }; void LoadShaders(); Shader::Pointer GetShaderImpl(const std::string& name) const; private: std::list shaders; static int shaderId; static const bool debug; public: /** * Constructor */ VtkShaderRepository(); /** * Destructor */ ~VtkShaderRepository(); ShaderProgram::Pointer CreateShaderProgram(); std::list GetShaders() const; IShaderRepository::Shader::Pointer GetShader(const std::string& name) const; IShaderRepository::Shader::Pointer GetShader(int id) const; /** \brief Adds all parsed shader uniforms to property list of the given DataNode; * used by mappers. */ void AddDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) const; /** \brief Applies shader and shader specific variables of the specified DataNode * to the VTK object by updating the shader variables of its vtkProperty. */ int LoadShader(std::istream& stream, const std::string& name); bool UnloadShader(int id); void UpdateShaderProgram(mitk::IShaderRepository::ShaderProgram* shaderProgram, DataNode* node, BaseRenderer* renderer) const; }; } //end of namespace mitk #endif diff --git a/Modules/VtkShaders/vtkXMLMaterial.cpp b/Modules/VtkShaders/vtkXMLMaterial.cpp index 8baa6c615b..4aa45127bf 100644 --- a/Modules/VtkShaders/vtkXMLMaterial.cpp +++ b/Modules/VtkShaders/vtkXMLMaterial.cpp @@ -1,280 +1,305 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkXMLMaterial.cxx 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. =========================================================================*/ #include "vtkXMLMaterial.h" #include "vtkObjectFactory.h" #include "vtkSmartPointer.h" #include "vtkXMLDataElement.h" #include "vtkXMLMaterialParser.h" #include "vtkXMLShader.h" #include #include class vtkXMLMaterialInternals { public: typedef std::vector VectorOfElements; typedef std::vector > VectorOfShaders; VectorOfElements Properties; VectorOfShaders VertexShaders; VectorOfShaders FragmentShaders; + VectorOfShaders GeometryShaders; VectorOfElements Textures; void Initialize() { this->Properties.clear(); this->VertexShaders.clear(); this->FragmentShaders.clear(); + this->GeometryShaders.clear(); this->Textures.clear(); } }; vtkStandardNewMacro(vtkXMLMaterial); //----------------------------------------------------------------------------- vtkXMLMaterial::vtkXMLMaterial() { this->RootElement = 0; this->Internals = new vtkXMLMaterialInternals; } //----------------------------------------------------------------------------- vtkXMLMaterial::~vtkXMLMaterial() { this->SetRootElement(0); delete this->Internals; } vtkXMLMaterial* vtkXMLMaterial::CreateInstance(const char* name) { if (!name) { return 0; } vtkXMLMaterialParser* parser = vtkXMLMaterialParser::New(); vtkXMLMaterial* material = vtkXMLMaterial::New(); parser->SetMaterial(material); // First, look for material library files. // Then, look for Repository files. char* filename = vtkXMLShader::LocateFile(name); if (filename) { parser->SetFileName( filename ); delete [] filename; parser->Parse(); parser->Delete(); return material; } parser->Delete(); material->Delete(); return NULL; } //----------------------------------------------------------------------------- void vtkXMLMaterial::SetRootElement(vtkXMLDataElement* root) { this->Internals->Initialize(); vtkSetObjectBodyMacro(RootElement, vtkXMLDataElement, root); if (this->RootElement) { // Update the internal data structure to // avoid repeated searches. int numElems = this->RootElement->GetNumberOfNestedElements(); for (int i=0; iRootElement->GetNestedElement(i); const char* name = elem->GetName(); if (!name) { continue; } if (strcmp(name, "Property") == 0) { this->Internals->Properties.push_back(elem); } else if (strcmp(name, "Shader") == 0) { vtkXMLShader* shader = vtkXMLShader::New(); shader->SetRootElement(elem); switch (shader->GetScope()) { case vtkXMLShader::SCOPE_VERTEX: this->Internals->VertexShaders.push_back(shader); break; case vtkXMLShader::SCOPE_FRAGMENT: this->Internals->FragmentShaders.push_back(shader); break; + case vtkXMLShader::SCOPE_GEOMETRY: + this->Internals->GeometryShaders.push_back(shader); + break; default: vtkErrorMacro("Invalid scope for shader: " << shader->GetName()); } shader->Delete(); } else if (strcmp(name, "Texture") == 0) { this->Internals->Textures.push_back(elem); } } } } //----------------------------------------------------------------------------- int vtkXMLMaterial::GetNumberOfProperties() { return static_cast(this->Internals->Properties.size()); } //----------------------------------------------------------------------------- int vtkXMLMaterial::GetNumberOfTextures() { return static_cast(this->Internals->Textures.size()); } //----------------------------------------------------------------------------- int vtkXMLMaterial::GetNumberOfVertexShaders() { return static_cast(this->Internals->VertexShaders.size()); } //----------------------------------------------------------------------------- int vtkXMLMaterial::GetNumberOfFragmentShaders() { return static_cast(this->Internals->FragmentShaders.size()); } +int vtkXMLMaterial::GetNumberOfGeometryShaders() +{ + return static_cast(this->Internals->GeometryShaders.size()); +} + //----------------------------------------------------------------------------- vtkXMLDataElement* vtkXMLMaterial::GetProperty(int id) { if (id < this->GetNumberOfProperties()) { return this->Internals->Properties[id]; } return NULL; } //----------------------------------------------------------------------------- vtkXMLDataElement* vtkXMLMaterial::GetTexture(int index) { if (index < this->GetNumberOfTextures()) { return this->Internals->Textures[index]; } return NULL; } //----------------------------------------------------------------------------- vtkXMLShader* vtkXMLMaterial::GetVertexShader(int id) { if (id < this->GetNumberOfVertexShaders()) { return this->Internals->VertexShaders[id].GetPointer(); } return NULL; } //----------------------------------------------------------------------------- vtkXMLShader* vtkXMLMaterial::GetFragmentShader(int id) { if (id < this->GetNumberOfFragmentShaders()) { return this->Internals->FragmentShaders[id].GetPointer(); } return NULL; } + +vtkXMLShader* vtkXMLMaterial::GetGeometryShader(int id) +{ + if (id < this->GetNumberOfGeometryShaders()) + { + return this->Internals->GeometryShaders[id].GetPointer(); + } + return NULL; +} + //---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Description: // Get the style the shaders. // \post valid_result: result==1 || result==2 int vtkXMLMaterial::GetShaderStyle() { int result = 1; int vStyle = 0; if (this->GetVertexShader()) { vStyle = this->GetVertexShader()->GetStyle(); } int fStyle = 0; if (this->GetFragmentShader()) { fStyle=this->GetFragmentShader()->GetStyle(); } - if (vStyle!=0 && fStyle!=0 && vStyle!=fStyle) + int gStyle = 0; + if (this->GetGeometryShader()) + { + gStyle=this->GetGeometryShader()->GetStyle(); + } + if (vStyle!=0 && fStyle!=0 && !gStyle && vStyle!=fStyle ) { vtkErrorMacro(<<"vertex shader and fragment shader style differ."); } else { if (vStyle!=0) { result = vStyle; } else { result = fStyle; } } assert("post: valid_result" && (result==1 || result==2) ); return result; } //----------------------------------------------------------------------------- void vtkXMLMaterial::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Number of Properties: " << this->GetNumberOfProperties() << endl; os << indent << "Number of Vertex Shaders: " << this->GetNumberOfVertexShaders() << endl; os << indent << "Number of Fragment Shaders: " << this->GetNumberOfFragmentShaders() << endl; os << indent << "RootElement: "; if (this->RootElement) { os << endl; this->RootElement->PrintSelf(os, indent.GetNextIndent()); } else { os << "(null)" << endl; } } diff --git a/Modules/VtkShaders/vtkXMLMaterial.h b/Modules/VtkShaders/vtkXMLMaterial.h index 6cf834632d..b561c09d7b 100644 --- a/Modules/VtkShaders/vtkXMLMaterial.h +++ b/Modules/VtkShaders/vtkXMLMaterial.h @@ -1,119 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkXMLMaterial.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. =========================================================================*/ // .NAME vtkXMLMaterial - encapsulates a VTK Material description. // .SECTION Description // vtkXMLMaterial encapsulates VTK Material description. It keeps a pointer // to vtkXMLDataElement that defines the material and provides // access to Shaders/Properties defined in it. // .SECTION Thanks // Shader support in VTK includes key contributions by Gary Templet at // Sandia National Labs. #ifndef __vtkXMLMaterial_h #define __vtkXMLMaterial_h #include "vtkRenderingCoreModule.h" // For export macro #include "vtkObject.h" class vtkXMLDataElement; class vtkXMLMaterialInternals; class vtkXMLShader; class vtkXMLMaterial : public vtkObject { public: static vtkXMLMaterial* New(); vtkTypeMacro(vtkXMLMaterial, vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Create a new instance. It searches for the material // using the following order: first, check the MaterialLibrary; second, // treat the name as an absolute path and try to locate it; third, // search the Material repository. Returns null is it fails to // locate the material. static vtkXMLMaterial* CreateInstance(const char* name); // Description: // Get number of elements of type Property. int GetNumberOfProperties(); // Description: // Get number of elements of type Texture. int GetNumberOfTextures(); // Description: // Get number of Vertex shaders. int GetNumberOfVertexShaders(); // Description: // Get number of fragment shaders. int GetNumberOfFragmentShaders(); + int GetNumberOfGeometryShaders(); // Description: // Get the ith vtkXMLDataElement of type . vtkXMLDataElement* GetProperty(int id=0); // Description: // Get the ith vtkXMLDataElement of type . vtkXMLDataElement* GetTexture(int id=0); // Description: // Get the ith vtkXMLDataElement of type . vtkXMLShader* GetVertexShader(int id=0); // Description: // Get the ith vtkXMLDataElement of type . vtkXMLShader* GetFragmentShader(int id=0); + vtkXMLShader* GetGeometryShader(int id=0); + // Description: // Get/Set the XML root element that describes this material. vtkGetObjectMacro(RootElement, vtkXMLDataElement); void SetRootElement(vtkXMLDataElement*); // Description: // Get the style the shaders. // \post valid_result: result==1 || result==2 int GetShaderStyle(); protected: vtkXMLMaterial(); ~vtkXMLMaterial(); vtkXMLDataElement* RootElement; vtkXMLMaterialInternals* Internals; private: vtkXMLMaterial(const vtkXMLMaterial&); // Not implemented. void operator=(const vtkXMLMaterial&); // Not implemented. }; #endif diff --git a/Modules/VtkShaders/vtkXMLShader.cpp b/Modules/VtkShaders/vtkXMLShader.cpp index fcf7a1cd84..5edfdda307 100644 --- a/Modules/VtkShaders/vtkXMLShader.cpp +++ b/Modules/VtkShaders/vtkXMLShader.cpp @@ -1,293 +1,300 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkXMLShader.cxx 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. =========================================================================*/ #include "vtkXMLShader.h" #include "vtkObjectFactory.h" #include "vtkXMLDataElement.h" #include #include vtkStandardNewMacro(vtkXMLShader); vtkCxxSetObjectMacro(vtkXMLShader, SourceLibraryElement, vtkXMLDataElement); //----------------------------------------------------------------------------- vtkXMLShader::vtkXMLShader() : Code(NULL), RootElement(NULL), SourceLibraryElement(NULL), Args(NULL) { } //----------------------------------------------------------------------------- vtkXMLShader::~vtkXMLShader() { if (this->RootElement) { this->RootElement->UnRegister(this); this->RootElement = 0; } this->SetSourceLibraryElement(0); this->SetCode(0); this->CleanupArgs(); } //----------------------------------------------------------------------------- void vtkXMLShader::SetRootElement(vtkXMLDataElement* root) { vtkSetObjectBodyMacro(RootElement, vtkXMLDataElement, root); this->SetCode(0); this->SetSourceLibraryElement(0); // release the SourceLibrary element. } //----------------------------------------------------------------------------- // Note that this method allocates a new string which must be deleted by // the caller. char* vtkXMLShader::LocateFile(const char* filename) { if(!filename) { return NULL; } // if filename is absolute path, return the same. if (vtksys::SystemTools::FileExists(filename)) { return vtksys::SystemTools::DuplicateString(filename); } // Fetch any runtime defined user paths for materials std::vector paths; std::string userpaths; vtksys::SystemTools::GetEnv("USER_MATERIALS_DIRS", userpaths); if (userpaths.size()>0) { vtksys::SystemTools::Split(userpaths.c_str(), paths, ';'); } #ifdef VTK_MATERIALS_DIRS // search thru default paths to locate file. vtksys::SystemTools::Split(VTK_MATERIALS_DIRS, paths, ';'); #endif for (unsigned int i =0; i < paths.size(); i++) { std::string path = paths[i]; if (path.size() == 0) { continue; } vtksys::SystemTools::ConvertToUnixSlashes(path); if (path[path.size()-1] != '/') { path += "/"; } path += filename; if (vtksys::SystemTools::FileExists(path.c_str())) { return vtksys::SystemTools::DuplicateString(path.c_str()); } } return NULL; } //----------------------------------------------------------------------------- int vtkXMLShader::GetScope() { if (this->RootElement) { const char* scope = this->RootElement->GetAttribute("scope"); if (!scope) { vtkErrorMacro("Shader description missing \"scope\" attribute."); } else if (strcmp(scope, "Vertex") == 0) { return vtkXMLShader::SCOPE_VERTEX; } else if (strcmp(scope, "Fragment") == 0) { return vtkXMLShader::SCOPE_FRAGMENT; } + else if (strcmp(scope, "Geometry") == 0) + { + return vtkXMLShader::SCOPE_GEOMETRY; + } } return vtkXMLShader::SCOPE_NONE; } // ---------------------------------------------------------------------------- // \post valid_result: result==1 || result==2 int vtkXMLShader::GetStyle() { int result=1; if(this->RootElement) { const char *loc=this->RootElement->GetAttribute("style"); if(loc==0) { // fine. this attribute is optional. } else { if(strcmp(loc,"1")==0) { // fine. default value. } else { if(strcmp(loc,"2")==0) { result=2; // new style } else { vtkErrorMacro(<<"style number not supported. Expect 1 or 2. We force it to be 1."); } } } } assert("post valid_result" && (result==1 || result==2) ); return result; } //----------------------------------------------------------------------------- const char* vtkXMLShader::GetName() { return (this->RootElement)? this->RootElement->GetAttribute("name") : 0; } //----------------------------------------------------------------------------- const char* vtkXMLShader::GetEntry() { return (this->RootElement)? this->RootElement->GetAttribute("entry") : 0; } //----------------------------------------------------------------------------- const char** vtkXMLShader::GetArgs() { this->CleanupArgs(); if (!this->RootElement || !this->RootElement->GetAttribute("args")) { return 0; } std::vector args; vtksys::SystemTools::Split(this->RootElement->GetAttribute("args"), args, ' '); int i; int size = static_cast(args.size()); if (size == 0) { return 0; } this->Args = new char*[size+1]; for (i=0; i < size; i++) { this->Args[i] = vtksys::SystemTools::DuplicateString(args[i].c_str()); } this->Args[size] = 0; return const_cast(this->Args); } //----------------------------------------------------------------------------- const char* vtkXMLShader::GetCode() { return this->RootElement->GetCharacterData(); } //----------------------------------------------------------------------------- void vtkXMLShader::CleanupArgs() { if (this->Args) { char** a = this->Args; while (*a) { delete [] (*a); a++; } delete [] this->Args; this->Args = 0; } } //----------------------------------------------------------------------------- void vtkXMLShader::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Name: " << (this->GetName()? this->GetName() : "(none)") << endl; os << indent << "Scope: "; switch(this->GetScope()) { case SCOPE_NONE: os << "None"; break; case SCOPE_MIXED: os << "Mixed"; break; case SCOPE_VERTEX: os << "Vertex"; break; case SCOPE_FRAGMENT: os << "Fragment"; break; + case SCOPE_GEOMETRY: + os << "Geometry"; + break; } os << endl; os << indent << "Entry: " << (this->GetEntry()? this->GetEntry() : "(none)") << endl; os << indent << "Args: "; const char** args = this->GetArgs(); if (!args) { os << "(none)" << endl; } else { while (*args) { os << indent << *args << " "; args++; } os << endl; } os << indent << "RootElement: "; if (this->RootElement) { os << endl; this->RootElement->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } } diff --git a/Modules/VtkShaders/vtkXMLShader.h b/Modules/VtkShaders/vtkXMLShader.h index e828343a56..5dcfa4d0e9 100644 --- a/Modules/VtkShaders/vtkXMLShader.h +++ b/Modules/VtkShaders/vtkXMLShader.h @@ -1,128 +1,129 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkXMLShader.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. =========================================================================*/ // .NAME vtkXMLShader - encapsulates a Shader XML description. // .SECTION Description // vtkXMLShader encapsulates the XML description for a Shader. // It provides convenient access to various attributes/properties // of a shader. // .SECTION Thanks // Shader support in VTK includes key contributions by Gary Templet at // Sandia National Labs. #ifndef __vtkXMLShader_h #define __vtkXMLShader_h #include "vtkRenderingCoreModule.h" // For export macro #include "vtkObject.h" class vtkXMLDataElement; class vtkXMLShader : public vtkObject { public: static vtkXMLShader* New(); vtkTypeMacro(vtkXMLShader, vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get/Set the XML root element that describes this shader. vtkGetObjectMacro(RootElement, vtkXMLDataElement); void SetRootElement(vtkXMLDataElement*); // Description: // Returns the type of the shader as defined in the XML description. int GetScope(); // Description: // Returns the style of the shader as optionaly defined in the XML // description. If not present, default style is 1. "style=2" means it is // a shader without a main(). In style 2, the "main" function for the vertex // shader part is void propFuncVS(void), the main function for the fragment // shader part is void propFuncFS(). This is useful when combining a shader // at the actor level and a shader defines at the renderer level, like // the depth peeling pass. // \post valid_result: result==1 || result==2 int GetStyle(); // Description: // Get the name of the Shader. const char* GetName(); // Description: // Get the entry point to the shader code as defined in the XML. const char* GetEntry(); // Description: // Get the shader code. const char* GetCode(); // Description: // Returns an null terminate array of the pointers to space sepatared Args // defined in the XML description. const char** GetArgs(); // Description: // Searches the file in the VTK_MATERIALS_DIRS. // Note that this allocates new memory for the string. // The caller must delete it. static char* LocateFile(const char* filename); //BTX enum ScopeCodes { SCOPE_NONE=0, SCOPE_MIXED, SCOPE_VERTEX, - SCOPE_FRAGMENT + SCOPE_FRAGMENT, + SCOPE_GEOMETRY }; //ETX protected: vtkXMLShader(); ~vtkXMLShader(); char* Code; // cache for the code. vtkSetStringMacro(Code); vtkXMLDataElement* RootElement; vtkXMLDataElement* SourceLibraryElement; void SetSourceLibraryElement(vtkXMLDataElement*); char** Args; void CleanupArgs(); private: vtkXMLShader(const vtkXMLShader&); // Not implemented. void operator=(const vtkXMLShader&); // Not implemented. }; #endif