From 9c3285bb9b084d18ef5fac4e370f8fd330866e28 Mon Sep 17 00:00:00 2001 From: Dharini Dutia Date: Thu, 11 Jan 2024 17:31:46 -0800 Subject: [PATCH 01/15] Support for Gazebo materials (#2269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test script tag Signed-off-by: Dharini Dutia * add dark grey before creating component Signed-off-by: Dharini Dutia * material parser Signed-off-by: Dharini Dutia * linters Signed-off-by: Dharini Dutia * Update src/rendering/MaterialParser/MaterialParser.cc Co-authored-by: Alejandro Hernández Cordero Signed-off-by: Dharini Dutia Signed-off-by: Dharini Dutia * fix configLoader, material struct and feedback Signed-off-by: Dharini Dutia * default color and todos Signed-off-by: Dharini Dutia * install/load one file, range based loop, hardcode dependent solid colors Signed-off-by: Dharini Dutia * fix install_dir property Signed-off-by: Dharini Dutia * credits, initializing cleanup Signed-off-by: Dharini Dutia * eof Signed-off-by: Dharini Dutia * reformat Signed-off-by: Dharini Dutia * add integration test Signed-off-by: Dharini Dutia * migration note Signed-off-by: Dharini Dutia * intends, default case, invalid color Signed-off-by: Dharini Dutia * optional materialValues, typo Signed-off-by: Dharini Dutia * feedback Signed-off-by: Dharini Dutia * size check Signed-off-by: Dharini Dutia * get color values Signed-off-by: Dharini Dutia * migration doc update Signed-off-by: Dharini Dutia --------- Signed-off-by: Dharini Dutia Signed-off-by: Dharini Dutia Co-authored-by: Alejandro Hernández Cordero --- include/gz/sim/InstallationDirectories.hh | 3 + src/CMakeLists.txt | 8 + src/InstallationDirectories.cc | 6 + src/SdfEntityCreator.cc | 47 +- src/rendering/MaterialParser/ConfigLoader.cc | 418 ++++ src/rendering/MaterialParser/ConfigLoader.hh | 173 ++ .../MaterialParser/MaterialParser.cc | 91 + .../MaterialParser/MaterialParser.hh | 54 + src/rendering/MaterialParser/gazebo.material | 1725 +++++++++++++++++ test/integration/CMakeLists.txt | 1 + test/integration/material.cc | 298 +++ tutorials/migration_sdf.md | 19 +- 12 files changed, 2832 insertions(+), 11 deletions(-) create mode 100644 src/rendering/MaterialParser/ConfigLoader.cc create mode 100644 src/rendering/MaterialParser/ConfigLoader.hh create mode 100644 src/rendering/MaterialParser/MaterialParser.cc create mode 100644 src/rendering/MaterialParser/MaterialParser.hh create mode 100644 src/rendering/MaterialParser/gazebo.material create mode 100644 test/integration/material.cc diff --git a/include/gz/sim/InstallationDirectories.hh b/include/gz/sim/InstallationDirectories.hh index 08e3b2b29e..a34478376b 100644 --- a/include/gz/sim/InstallationDirectories.hh +++ b/include/gz/sim/InstallationDirectories.hh @@ -50,6 +50,9 @@ namespace gz /// \brief getWorldInstallDir return the world install dir GZ_SIM_VISIBLE std::string getWorldInstallDir(); + + /// \brief getMediaInstallDir return the media install dir + GZ_SIM_VISIBLE std::string getMediaInstallDir(); } } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8466679071..af621745a7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -46,6 +46,11 @@ set(cli_sources cmd/ModelCommandAPI.cc ) +set(material_sources + rendering/MaterialParser/MaterialParser.cc + rendering/MaterialParser/ConfigLoader.cc +) + set (sources Actor.cc Barrier.cc @@ -78,6 +83,7 @@ set (sources ${network_sources} ${comms_sources} ${component_sources} + ${material_sources} ) set (gtest_sources @@ -186,7 +192,9 @@ set_property( GZ_SIM_PLUGIN_RELATIVE_INSTALL_DIR="${GZ_LIB_INSTALL_DIR}/gz-${GZ_DESIGNATION}-${PROJECT_VERSION_MAJOR}/plugins" GZ_SIM_GUI_PLUGIN_RELATIVE_INSTALL_DIR="${GZ_LIB_INSTALL_DIR}/gz-${GZ_DESIGNATION}-${PROJECT_VERSION_MAJOR}/plugins/gui" GZ_SIM_WORLD_RELATIVE_INSTALL_DIR="${GZ_DATA_INSTALL_DIR}/worlds" + GZ_SIM_MEDIA_RELATIVE_INSTALL_DIR="${GZ_DATA_INSTALL_DIR}/media" ) +install(FILES "rendering/MaterialParser/gazebo.material" DESTINATION ${GZ_DATA_INSTALL_DIR}/media) target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME} PUBLIC diff --git a/src/InstallationDirectories.cc b/src/InstallationDirectories.cc index 2aa64e334d..f7b22f7cf6 100644 --- a/src/InstallationDirectories.cc +++ b/src/InstallationDirectories.cc @@ -62,6 +62,12 @@ std::string getWorldInstallDir() getInstallPrefix(), GZ_SIM_WORLD_RELATIVE_INSTALL_DIR); } +std::string getMediaInstallDir() +{ + return gz::common::joinPaths( + getInstallPrefix(), GZ_SIM_MEDIA_RELATIVE_INSTALL_DIR); +} + } } } diff --git a/src/SdfEntityCreator.cc b/src/SdfEntityCreator.cc index fba9663f3e..0117768c83 100644 --- a/src/SdfEntityCreator.cc +++ b/src/SdfEntityCreator.cc @@ -95,6 +95,8 @@ #include "gz/sim/components/World.hh" #endif +#include "rendering/MaterialParser/MaterialParser.hh" + class gz::sim::SdfEntityCreatorPrivate { /// \brief Pointer to entity component manager. We don't assume ownership. @@ -114,6 +116,9 @@ class gz::sim::SdfEntityCreatorPrivate /// \brief Keep track of new visuals being added, so we load their plugins /// only after we have their scoped name. public: std::map newVisuals; + + /// \brief Parse Gazebo defined materials for visuals + public: MaterialParser materialParser; }; using namespace gz; @@ -204,6 +209,7 @@ SdfEntityCreator::SdfEntityCreator(EntityComponentManager &_ecm, { this->dataPtr->ecm = &_ecm; this->dataPtr->eventManager = &_eventManager; + this->dataPtr->materialParser.Load(); } ///////////////////////////////////////////////// @@ -834,8 +840,47 @@ Entity SdfEntityCreator::CreateEntities(const sdf::Visual *_visual) // \todo(louise) Populate with default material if undefined if (_visual->Material()) { + sdf::Material visualMaterial = *_visual->Material(); + if (!_visual->Material()->ScriptUri().empty()) + { + gzwarn << "Gazebo does not support Ogre material scripts. See " << + "https://gazebosim.org/api/sim/8/migrationsdf.html#:~:text=Materials " << + "for details." << std::endl; + std::string scriptUri = visualMaterial.ScriptUri(); + if (scriptUri != "file://media/materials/scripts/gazebo.material") { + gzwarn << "Custom material scripts are not supported." + << std::endl; + } + } + if (!_visual->Material()->ScriptName().empty()) + { + std::string scriptName = visualMaterial.ScriptName(); + + if ((scriptName.find("Gazebo/") == 0u)) + { + gzwarn << "Using an internal gazebo.material to parse " + << scriptName << std::endl; + std::optional parsed = + this->dataPtr->materialParser.GetMaterialValues(scriptName); + + if(parsed.has_value()) + { + visualMaterial.SetAmbient + (parsed->ambient.value_or(visualMaterial.Ambient())); + visualMaterial.SetDiffuse + (parsed->diffuse.value_or(visualMaterial.Diffuse())); + visualMaterial.SetSpecular + (parsed->specular.value_or(visualMaterial.Specular())); + } + else + { + gzwarn << "Material " << scriptName << + " not recognized or supported, using default." << std::endl; + } + } + } this->dataPtr->ecm->CreateComponent(visualEntity, - components::Material(*_visual->Material())); + components::Material(visualMaterial)); } // store the plugin in a component diff --git a/src/rendering/MaterialParser/ConfigLoader.cc b/src/rendering/MaterialParser/ConfigLoader.cc new file mode 100644 index 0000000000..ef35998a47 --- /dev/null +++ b/src/rendering/MaterialParser/ConfigLoader.cc @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +// This code is adapted from https://wiki.ogre3d.org/All-purpose+script+parser + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "gz/sim/InstallationDirectories.hh" + +#include "ConfigLoader.hh" + +using namespace gz; +using namespace sim; + +void ConfigLoader::loadMaterialFiles(ConfigLoader * c) +{ + try + { + std::string installedConfig = common::joinPaths( + gz::sim::getMediaInstallDir(), + "gazebo.material"); + std::ifstream in(installedConfig, std::ios::binary); + c->parseScript(in); + } + catch(std::filesystem::filesystem_error & e) + { + gzerr << e.what() << std::endl; + } +} + +ConfigLoader::ConfigLoader() +{ +} + +ConfigLoader::~ConfigLoader() +{ + clearScriptList(); +} + +void ConfigLoader::clearScriptList() +{ + for (auto & i : m_scriptList) { + delete i.second; + } + m_scriptList.clear(); +} + +ConfigNode * ConfigLoader::getConfigScript(const std::string & name) +{ + auto i = m_scriptList.find(name); + // If found.. + if (i != m_scriptList.end()) { + return i->second; + } else { + return nullptr; + } +} + +std::map ConfigLoader::getAllConfigScripts() +{ + return m_scriptList; +} + +void ConfigLoader::parseScript(std::ifstream & stream) +{ + // Get first token + _nextToken(stream); + if (tok == TOKEN_EOF) { + stream.close(); + return; + } + + // Parse the script + _parseNodes(stream, 0); + + stream.close(); +} + +void ConfigLoader::_nextToken(std::ifstream & stream) +{ + lastTok = tok; + lastTokVal = tokVal; + + // EOF token + if (stream.eof()) { + tok = TOKEN_EOF; + return; + } + + // Get next character + int ch = stream.get(); + if (ch == -1) { + tok = TOKEN_EOF; + return; + } + // Skip leading spaces / tabs + while ((ch == ' ' || ch == 9) && !stream.eof()) { + ch = stream.get(); + } + + if (stream.eof()) { + tok = TOKEN_EOF; + return; + } + + // Newline token + if (ch == '\r' || ch == '\n') { + do{ + ch = stream.get(); + } while ((ch == '\r' || ch == '\n') && !stream.eof()); + + stream.unget(); + + tok = TOKEN_NewLine; + return; + } else if (ch == '{') { + // Open brace token + tok = TOKEN_OpenBrace; + return; + } else if (ch == '}') { + // Close brace token + tok = TOKEN_CloseBrace; + return; + } + + // Text token + if (ch < 32 || ch > 122) { // Verify valid char + throw std::runtime_error( + "Parse Error: Invalid character, ConfigLoader::load()"); + } + + tokVal = ""; + tok = TOKEN_Text; + do{ + // Skip comments + if (ch == '/') { + int ch2 = stream.peek(); + + // C++ style comment (//) + if (ch2 == '/') { + stream.get(); + do{ + ch = stream.get(); + } while (ch != '\r' && ch != '\n' && !stream.eof()); + + tok = TOKEN_NewLine; + return; + } else if (ch2 == '*') { + stream.get(); + do{ + ch = stream.get(); + ch2 = stream.peek(); + } while (!(ch == '*' && ch2 == '/') && !stream.eof()); + stream.get(); + do{ + ch = stream.get(); + } while (ch != '\r' && ch != '\n' && !stream.eof()); + continue; + } + } + + // Add valid char to tokVal + tokVal += static_cast(ch); + + // Next char + ch = stream.get(); + } while (ch > 32 && ch <= 122 && !stream.eof()); + + stream.unget(); + + return; +} + +void ConfigLoader::_skipNewLines(std::ifstream & stream) +{ + while (tok == TOKEN_NewLine) { + _nextToken(stream); + } +} + +void ConfigLoader::_parseNodes(std::ifstream & stream, ConfigNode * parent) +{ + typedef std::pair < std::string, ConfigNode * > ScriptItem; + + while (true) { + switch (tok) { + // Node + case TOKEN_Text: + // Add the new node + ConfigNode * newNode; + if (parent) { + newNode = parent->addChild(tokVal); + } else { + newNode = new ConfigNode(0, tokVal); + } + + // Get values + _nextToken(stream); + while (tok == TOKEN_Text) { + newNode->addValue(tokVal); + _nextToken(stream); + } + + // Add root nodes to scriptList + if (!parent) { + std::string key; + + if (newNode->getValues().empty()) { + key = newNode->getName() + ' '; + } else { + key = newNode->getName() + ' ' + newNode->getValues().front(); + } + + m_scriptList.insert(ScriptItem(key, newNode)); + } + + _skipNewLines(stream); + + // Add any sub-nodes + if (tok == TOKEN_OpenBrace) { + // Parse nodes + _nextToken(stream); + _parseNodes(stream, newNode); + // Check for matching closing brace + if (tok != TOKEN_CloseBrace) { + throw std::runtime_error("Parse Error: Expecting closing brace"); + } + _nextToken(stream); + _skipNewLines(stream); + } + + break; + + // Out of place brace + case TOKEN_OpenBrace: + throw std::runtime_error("Parse Error: Opening brace out of plane"); + break; + + // Return if end of nodes have been reached + case TOKEN_CloseBrace: + return; + + // Return if reached end of file + case TOKEN_EOF: + return; + + case TOKEN_NewLine: + _nextToken(stream); + break; + + default: + break; + } + } +} + +ConfigNode::ConfigNode(ConfigNode * parent, const std::string & name) +{ + m_name = name; + m_parent = parent; + _removeSelf = true; // For proper destruction + m_lastChildFound = -1; + + // Add self to parent's child list + // (unless this is the root node being created) + if (parent != NULL) { + m_parent->m_children.push_back(this); + _iter = --(m_parent->m_children.end()); + } +} + +ConfigNode::~ConfigNode() +{ + // Delete all children + std::vector < ConfigNode * > ::iterator i; + for (i = m_children.begin(); i != m_children.end(); i++) { + ConfigNode * node = *i; + node->_removeSelf = false; + delete node; + } + m_children.clear(); + + // Remove self from parent's child list + if (_removeSelf && m_parent != NULL) { + m_parent->m_children.erase(_iter); + } +} + +void ConfigNode::getColorValues(gz::math::Color & colorValues, + unsigned int size) +{ + std::vector floatValues; + ConfigNode::getValuesInFloat(floatValues); + if (floatValues.size() < size) { + gzerr << "Bad material file." << std::endl; + floatValues.resize(size); + } + if (size == 3) { + colorValues = gz::math::Color(floatValues[0], floatValues[1], + floatValues[2]); + } + if (size == 4) { + colorValues = gz::math::Color(floatValues[0], floatValues[1], + floatValues[2], floatValues[3]); + } +} + +ConfigNode * ConfigNode::addChild( + const std::string & name, bool replaceExisting) +{ + if (replaceExisting) { + ConfigNode * node = findChild(name, false); + if (node) { + return node; + } + } + return new ConfigNode(this, name); +} + +ConfigNode * ConfigNode::findChild(const std::string & name, bool recursive) +{ + int indx, prevC, nextC; + int childCount = static_cast(m_children.size()); + + if (m_lastChildFound != -1) { + // If possible, try checking nodes neighboring the last successful search + // (often nodes searched for in sequence, so this will std search speeds). + prevC = m_lastChildFound - 1; + if (prevC < 0) { + prevC = 0; + } else if (prevC >= childCount) { + prevC = childCount - 1; + } + nextC = m_lastChildFound + 1; + if (nextC < 0) { + nextC = 0; + } else if (nextC >= childCount) { + nextC = childCount - 1; + } + for (indx = prevC; indx <= nextC; ++indx) { + ConfigNode * node = m_children[indx]; + if (node->m_name == name) { + m_lastChildFound = indx; + return node; + } + } + + // If not found that way, search for the node from start to finish, + // avoiding the already searched area above. + for (indx = nextC + 1; indx < childCount; ++indx) { + ConfigNode * node = m_children[indx]; + if (node->m_name == name) { + m_lastChildFound = indx; + return node; + } + } + for (indx = 0; indx < prevC; ++indx) { + ConfigNode * node = m_children[indx]; + if (node->m_name == name) { + m_lastChildFound = indx; + return node; + } + } + } else { + // Search for the node from start to finish + for (indx = 0; indx < childCount; ++indx) { + ConfigNode * node = m_children[indx]; + if (node->m_name == name) { + m_lastChildFound = indx; + return node; + } + } + } + + // If not found, search child nodes (if recursive == true) + if (recursive) { + for (indx = 0; indx < childCount; ++indx) { + m_children[indx]->findChild(name, recursive); + } + } + + // Not found anywhere + return NULL; +} + +void ConfigNode::setParent(ConfigNode * newParent) +{ + // Remove self from current parent + m_parent->m_children.erase(_iter); + + // Set new parent + m_parent = newParent; + + // Add self to new parent + m_parent->m_children.push_back(this); + _iter = --(m_parent->m_children.end()); +} diff --git a/src/rendering/MaterialParser/ConfigLoader.hh b/src/rendering/MaterialParser/ConfigLoader.hh new file mode 100644 index 0000000000..3e2bca3fd2 --- /dev/null +++ b/src/rendering/MaterialParser/ConfigLoader.hh @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +// This code is adapted from https://wiki.ogre3d.org/All-purpose+script+parser + +#ifndef RENDERING__MATERIALPARSER__CONFIGLOADER_HH_ +#define RENDERING__MATERIALPARSER__CONFIGLOADER_HH_ + +#include +#include +#include +#include +#include + +namespace gz +{ +namespace sim +{ +class ConfigNode; + +class ConfigLoader +{ +public: + static void loadMaterialFiles(ConfigLoader * c); + + ConfigLoader(); + + ~ConfigLoader(); + + std::string m_fileEnding; + + // For a line like + // entity animals/dog + // { + // ... + // } + // The type is "entity" and the name is "animals/dog" + // Or if animal/dog was not there then name is "" + virtual ConfigNode * getConfigScript(const std::string & name); + + virtual std::map getAllConfigScripts(); + + virtual void parseScript(std::ifstream & stream); + +protected: + float m_LoadOrder; + // like "*.object" + + std::map m_scriptList; + + enum Token + { + TOKEN_Text, + TOKEN_NewLine, + TOKEN_OpenBrace, + TOKEN_CloseBrace, + TOKEN_EOF, + }; + + Token tok, lastTok; + std::string tokVal, lastTokVal; + + void _parseNodes(std::ifstream & stream, ConfigNode * parent); + void _nextToken(std::ifstream & stream); + void _skipNewLines(std::ifstream & stream); + + virtual void clearScriptList(); +}; + +class ConfigNode +{ +public: + explicit ConfigNode(ConfigNode * parent, + const std::string & name = "untitled"); + + ~ConfigNode(); + + inline void setName(const std::string & name) + { + this->m_name = name; + } + + inline std::string & getName() + { + return m_name; + } + + inline void addValue(const std::string & value) + { + m_values.push_back(value); + } + + inline void clearValues() + { + m_values.clear(); + } + + inline std::vector & getValues() + { + return m_values; + } + + inline const std::string & getValue(unsigned int index = 0) + { + assert(index < m_values.size()); + return m_values[index]; + } + + inline void getValuesInFloat(std::vector & floatValues) + { + for (const auto & str : m_values) { + floatValues.push_back(std::stof(str)); + } + } + + void getColorValues(math::Color & colorValues, unsigned int size); + + ConfigNode * addChild( + const std::string & name = "untitled", bool replaceExisting = false); + + ConfigNode * findChild(const std::string & name, bool recursive = false); + + inline std::vector & getChildren() + { + return m_children; + } + + inline ConfigNode * getChild(unsigned int index = 0) + { + assert(index < m_children.size()); + return m_children[index]; + } + + void setParent(ConfigNode * newParent); + + inline ConfigNode * getParent() + { + return m_parent; + } + +private: + std::string m_name; + + std::vector m_values; + + std::vector m_children; + + ConfigNode * m_parent; + + // The last child node's index found with a call to findChild() + int m_lastChildFound; + + std::vector ::iterator _iter; + + bool _removeSelf; +}; +} // namespace sim +} // namespace gz + +#endif // RENDERING__MATERIALPARSER__CONFIGLOADER_HH_ diff --git a/src/rendering/MaterialParser/MaterialParser.cc b/src/rendering/MaterialParser/MaterialParser.cc new file mode 100644 index 0000000000..2d6e2e7b0d --- /dev/null +++ b/src/rendering/MaterialParser/MaterialParser.cc @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +#include "MaterialParser.hh" + +using namespace gz; +using namespace sim; + +///////////////////////////////////////////////// +MaterialParser::MaterialParser() + : configLoader() +{ +} + +///////////////////////////////////////////////// +void MaterialParser::Load() +{ + ConfigLoader::loadMaterialFiles(&this->configLoader); +} + +///////////////////////////////////////////////// +std::optional MaterialParser::GetMaterialValues( + const std::string& material) +{ + std::optional values = std::nullopt; + std::map scripts = + this->configLoader.getAllConfigScripts(); + + std::map ::iterator it; + + for (it = scripts.begin(); it != scripts.end(); ++it) { + std::string name = it->first; + if (name.find(material) != std::string::npos) { + if (!values) { + values = MaterialValues(); + } + ConfigNode * node = it->second; + + ConfigNode * techniqueNode = node->findChild("technique"); + if (techniqueNode) { + ConfigNode * passNode = techniqueNode->findChild("pass"); + if (passNode) { + ConfigNode * ambientNode = passNode->findChild("ambient"); + if (ambientNode) { + gz::math::Color ambientValues; + ambientNode->getColorValues(ambientValues, 3); + values->ambient.emplace(ambientValues); + } + + ConfigNode * diffuseNode = passNode->findChild("diffuse"); + if (diffuseNode) { + gz::math::Color diffuseValues; + diffuseNode->getColorValues(diffuseValues, 3); + values->diffuse.emplace(diffuseValues); + } + + ConfigNode * specularNode = passNode->findChild("specular"); + if (specularNode) { + gz::math::Color specularValues; + specularNode->getColorValues(specularValues, 4); + // Using first four values for specular as + // Gazebo doesn't support shininess + values->specular.emplace(specularValues); + } + } + } + // \todo Handle dependent materials + } + } + return values; +} diff --git a/src/rendering/MaterialParser/MaterialParser.hh b/src/rendering/MaterialParser/MaterialParser.hh new file mode 100644 index 0000000000..17b542ba0b --- /dev/null +++ b/src/rendering/MaterialParser/MaterialParser.hh @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef RENDERING__MATERIALPARSER__MATERIALPARSER_HH_ +#define RENDERING__MATERIALPARSER__MATERIALPARSER_HH_ + +#include +#include + +#include + +#include "ConfigLoader.hh" + +namespace gz +{ +namespace sim +{ +class MaterialParser +{ + public: + struct MaterialValues + { + std::optional ambient; + std::optional diffuse; + std::optional specular; + }; + + MaterialParser(); + + void Load(); + + std::optional GetMaterialValues(const std::string& material); + + private: + ConfigLoader configLoader; +}; +} // namespace sim +} // namespace gz + +#endif // RENDERING__MATERIALPARSER__MATERIALPARSER_HH_ diff --git a/src/rendering/MaterialParser/gazebo.material b/src/rendering/MaterialParser/gazebo.material new file mode 100644 index 0000000000..cca4f4ceff --- /dev/null +++ b/src/rendering/MaterialParser/gazebo.material @@ -0,0 +1,1725 @@ +vertex_program grid_vp_glsl glsl +{ + source grid_vp.glsl +} + +fragment_program grid_fp_glsl glsl +{ + source grid_fp.glsl +} + +material grid +{ + technique + { + pass + { + vertex_program_ref grid_vp_glsl {} + fragment_program_ref grid_fp_glsl {} + } + } +} + +vertex_program Gazebo/DepthMapVS glsl +{ + source depth_map.vert + + default_params + { + param_named_auto texelOffsets texel_offsets + } +} + +fragment_program Gazebo/DepthMapFS glsl +{ + source depth_map.frag + + default_params + { + param_named_auto pNear near_clip_distance + param_named_auto pFar far_clip_distance + } +} + +material Gazebo/DepthMap +{ + technique + { + pass + { + vertex_program_ref Gazebo/DepthMapVS { } + fragment_program_ref Gazebo/DepthMapFS { } + } + } +} + +vertex_program Gazebo/XYZPointsVS glsl +{ + source depth_points_map.vert +} + +fragment_program Gazebo/XYZPointsFS glsl +{ + source depth_points_map.frag + + default_params + { + param_named_auto width viewport_width + param_named_auto height viewport_height + } +} + +material Gazebo/XYZPoints +{ + technique + { + pass pcd_tex + { + separate_scene_blend one zero one zero + + vertex_program_ref Gazebo/XYZPointsVS { } + fragment_program_ref Gazebo/XYZPointsFS { } + } + } +} + +material Gazebo/Reflectance +{ + technique + { + pass + { + lighting off + texture_unit + { + } + } + } +} + +vertex_program Gazebo/XYZNormalsVS glsl +{ + source depth_normals_map.vert +} + +fragment_program Gazebo/XYZNormalsFS glsl +{ + source depth_normals_map.frag +} + +material Gazebo/XYZNormals +{ + technique + { + pass normals_tex + { + separate_scene_blend one zero one zero + + vertex_program_ref Gazebo/XYZNormalsVS { } + fragment_program_ref Gazebo/XYZNormalsFS { } + } + } +} + +vertex_program Gazebo/LaserScan1stVS glsl +{ + source laser_1st_pass.vert +} + +fragment_program Gazebo/LaserScan1stFS glsl +{ + source laser_1st_pass.frag + + default_params + { + param_named retro float 0.0 + param_named_auto near near_clip_distance + param_named_auto far far_clip_distance + } +} + +material Gazebo/LaserScan1st +{ + technique + { + pass laser_tex + { + separate_scene_blend one zero one zero + + vertex_program_ref Gazebo/LaserScan1stVS { } + fragment_program_ref Gazebo/LaserScan1stFS { } + } + } +} + +vertex_program Gazebo/LaserScan2ndVS glsl +{ + source laser_2nd_pass.vert +} + +fragment_program Gazebo/LaserScan2ndFS glsl +{ + source laser_2nd_pass.frag + + default_params + { + param_named tex1 int 0 + param_named tex2 int 1 + param_named tex3 int 2 + param_named_auto texSize texture_size 0 + } +} + +material Gazebo/LaserScan2nd +{ + technique + { + pass laser_tex_2nd + { + separate_scene_blend one zero one zero + + vertex_program_ref Gazebo/LaserScan2ndVS { } + fragment_program_ref Gazebo/LaserScan2ndFS { } + } + } +} + +material Gazebo/Grey +{ + technique + { + pass main + { + ambient .3 .3 .3 1.0 + diffuse .7 .7 .7 1.0 + specular 0.01 0.01 0.01 1.000000 1.500000 + } + } +} +material Gazebo/Gray : Gazebo/Grey +{ + technique + { + pass main + { + ambient .3 .3 .3 1.0 + diffuse .7 .7 .7 1.0 + specular 0.01 0.01 0.01 1.000000 1.500000 + } + } +} + +material Gazebo/DarkGrey +{ + technique + { + pass main + { + ambient .175 .175 .175 1.0 + diffuse .175 .175 .175 1.0 + specular .175 .175 .175 1.000000 1.500000 + } + } +} + +material Gazebo/DarkGray : Gazebo/DarkGrey +{ + technique + { + pass main + { + ambient .175 .175 .175 1.0 + diffuse .175 .175 .175 1.0 + specular .175 .175 .175 1.000000 1.500000 + } + } +} + +material Gazebo/White +{ + technique + { + pass ambient + { + ambient 1 1 1 1 + } + + pass light + { + diffuse 1 1 1 1 + specular .1 .1 .1 128 + } + } +} + +material Gazebo/FlatBlack +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 + diffuse 0.1 0.1 0.1 + specular 0.01 0.01 0.01 1.0 1.0 + } + } +} + +material Gazebo/Black +{ + technique + { + pass + { + ambient 0 0 0 1 + diffuse 0 0 0 1 + specular 0.1 0.1 0.1 1 5.0 + } + } +} + + +material Gazebo/Red +{ + technique + { + pass ambient + { + ambient 1 0 0 + diffuse 1 0 0 + specular 0.1 0.1 0.1 1 1 + } + } +} + +material Gazebo/RedBright +{ + technique + { + pass ambient + { + ambient 0.87 0.26 0.07 + diffuse 0.87 0.26 0.07 + specular 0.87 0.26 0.07 1 1 + } + } +} + +material Gazebo/Green +{ + technique + { + pass ambient + { + ambient 0 1 0 + diffuse 0 1 0 + specular 0.1 0.1 0.1 1 1 + } + } +} + +material Gazebo/Blue +{ + technique + { + pass ambient + { + ambient 0 0 1 + diffuse 0 0 1 + specular 0.1 0.1 0.1 1 1 + } + } +} + +material Gazebo/SkyBlue +{ + technique + { + pass ambient + { + ambient 0.13 0.44 0.70 + diffuse 0 0 1 + specular 0.1 0.1 0.1 1 1 + } + } +} + +material Gazebo/Yellow +{ + technique + { + pass ambient + { + ambient 1 1 0 1 + diffuse 1 1 0 1 + specular 0 0 0 0 0 + } + } +} + +material Gazebo/ZincYellow +{ + technique + { + pass ambient + { + ambient 0.9725 0.9529 0.2078 1 + diffuse 0.9725 0.9529 0.2078 1 + specular 0.9725 0.9529 0.2078 1 1 + } + } +} + +material Gazebo/DarkYellow +{ + technique + { + pass ambient + { + ambient 0.7 0.7 0 1 + diffuse 0.7 0.7 0 1 + specular 0 0 0 0 0 + } + } +} + + +material Gazebo/Purple +{ + technique + { + pass ambient + { + ambient 1 0 1 + diffuse 1 0 1 + specular 0.1 0.1 0.1 1 1 + } + } +} + +material Gazebo/Turquoise +{ + technique + { + pass ambient + { + ambient 0 1 1 + diffuse 0 1 1 + specular 0.1 0.1 0.1 1 1 + } + } +} + +material Gazebo/Orange +{ + technique + { + pass ambient + { + lighting on + + ambient 1 0.5088 0.0468 1 + diffuse 1 0.5088 0.0468 1 + specular 0.5 0.5 0.5 128 + } + } +} + +material Gazebo/Indigo +{ + technique + { + pass ambient + { + ambient 0.33 0.0 0.5 + diffuse 0.33 0.0 0.5 + specular 0.1 0.1 0.1 1 + } + } +} + +material Gazebo/WhiteGlow : Gazebo/White +{ + technique + { + pass light + { + emissive 1 1 1 + } + } +} + +material Gazebo/RedGlow +{ + technique + { + pass ambient + { + ambient 1 0 0 + diffuse 1 0 0 + emissive 1 0 0 + specular 0 0 0 128 + } + + pass light + { + ambient 1 0 0 + diffuse 1 0 0 + emissive 1 0 0 + specular 1 0 0 128 + } + } +} + + + +material Gazebo/GreenGlow : Gazebo/Green +{ + technique + { + pass ambient + { + emissive 0 1 0 + } + + pass light + { + emissive 0 1 0 + } + } +} + +material Gazebo/BlueGlow : Gazebo/Blue +{ + technique + { + pass light + { + emissive 0 0 1 + } + } +} + +material Gazebo/YellowGlow : Gazebo/Yellow +{ + technique + { + pass light + { + emissive 1 1 0 + } + } +} + +material Gazebo/PurpleGlow : Gazebo/Purple +{ + technique + { + pass light + { + emissive 1 0 1 + } + } +} + +material Gazebo/TurquoiseGlow : Gazebo/Turquoise +{ + technique + { + pass light + { + emissive 0 1 1 + } + } +} + +material Gazebo/TurquoiseGlowOutline +{ + technique + { + pass ambient + { + scene_blend alpha_blend + //lighting off + + diffuse 0 1 1 1 + specular .1 .1 .1 128 + } + + pass ambient2 + { + scene_blend alpha_blend + + diffuse 0 1 1 + specular .1 .1 .1 128 + emissive 0 1 1 + + polygon_mode wireframe + } + } +} + +material Gazebo/RedTransparentOverlay +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + lighting off + depth_check off + + texture_unit + { + colour_op_ex source1 src_manual src_current 1 0 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/BlueTransparentOverlay +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + lighting off + depth_check off + + texture_unit + { + colour_op_ex source1 src_manual src_current 0 0 1 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/GreenTransparentOverlay +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + lighting off + depth_check off + + texture_unit + { + colour_op_ex source1 src_manual src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/OrangeTransparentOverlay +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + lighting off + depth_check off + ambient 1 0.5088 0.0468 + + texture_unit + { + colour_op_ex source1 src_manual src_current 1 0.5088 0.0468 + alpha_op_ex source1 src_manual src_current 0.8 + } + } + } +} + +material Gazebo/DarkOrangeTransparentOverlay +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + lighting off + depth_check off + ambient 0.6 0.305 0.028 + + texture_unit + { + colour_op_ex source1 src_manual src_current 0.6 0.305 0.028 + alpha_op_ex source1 src_manual src_current 0.8 + } + } + } +} + +material Gazebo/RedTransparent +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + lighting off + + texture_unit + { + colour_op_ex source1 src_manual src_current 1 0 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/GreenTransparent +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + + ambient 0.0 1.0 0.0 1 + diffuse 0.0 1.0 0.0 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/BlueTransparent +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + + ambient 0.0 0.0 1.0 1 + diffuse 0.0 0.0 1.0 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/DarkMagentaTransparent +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + + ambient 0.6 0.0 0.6 1 + diffuse 0.6 0.0 0.6 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0.6 0 0.6 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/GreyTransparent +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + + ambient 0.5 0.5 0.5 1 + diffuse 0.5 0.5 0.5 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/BlackTransparent +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + + ambient 0.0 0.0 0.0 1 + diffuse 0.0 0.0 0.0 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/YellowTransparent +{ + technique + { + pass + { + scene_blend alpha_blend + depth_write off + + ambient 1.0 1.0 0.0 1 + diffuse 1.0 1.0 0.0 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.5 + } + } + } +} + +material Gazebo/LightOn +{ + technique + { + pass ambient + { + diffuse 0 1 0 + ambient 0 1 0 + emissive 0 1 0 + } + } +} + +material Gazebo/LightOff +{ + technique + { + pass ambient + { + diffuse 1 0 0 + ambient 1 0 0 + emissive 1 0 0 + } + } +} + +material Gazebo/LightBlueLaser +{ + receive_shadows off + + technique + { + pass + { + scene_blend alpha_blend + depth_write off + cull_hardware none + + ambient 0.5 0.5 1.0 1 + diffuse 0.5 0.5 1.0 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.4 + } + + } + } +} + +material Gazebo/BlueLaser +{ + receive_shadows off + + technique + { + pass + { + scene_blend alpha_blend + depth_write off + cull_hardware none + + ambient 0.0 0.0 1.0 1 + diffuse 0.0 0.0 1.0 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.4 + } + + } + } +} + +material Gazebo/OrangeTransparent +{ + receive_shadows off + + technique + { + pass + { + scene_blend alpha_blend + depth_write off + + ambient 1.0 0.44 0.0 1 + diffuse 1.0 0.44 0.0 1 + + texture_unit + { + colour_op_ex source1 src_current src_current 0 1 0 + alpha_op_ex source1 src_manual src_current 0.4 + } + + } + } +} + + +material Gazebo/JointAnchor +{ + receive_shadows off + + technique + { + pass + { + ambient 1.000000 1.000000 1.000000 1.000000 + diffuse 1.000000 1.000000 1.000000 1.000000 + specular 1.000000 1.000000 1.000000 1.000000 + emissive 1.000000 1.000000 1.000000 1.000000 + lighting off + } + } +} + +material Gazebo/CoM +{ + technique + { + pass + { + ambient 0.5 0.5 0.5 1.000000 + + texture_unit + { + texture com.png + } + } + } +} + +material Gazebo/WoodFloor +{ + receive_shadows on + + technique + { + pass + { + ambient 0.5 0.5 0.5 1.000000 + + texture_unit + { + texture hardwood_floor.jpg + } + } + } +} + +material Gazebo/CeilingTiled +{ + receive_shadows on + + technique + { + pass + { + ambient 0.5 0.5 0.5 1.000000 + + texture_unit + { + texture ceiling_tiled.jpg + } + } + } +} + +material Gazebo/PaintedWall +{ + receive_shadows on + + technique + { + pass + { + ambient 1.0 1.0 1.0 1.000000 + + texture_unit + { + texture paintedWall.jpg + } + } + } +} + +material Gazebo/PioneerBody +{ + receive_shadows on + technique + { + pass Ambient + { + ambient 0.5 0 0 + + texture_unit + { + texture pioneerBody.jpg + filtering trilinear + } + } + pass DirectionalLight + { + ambient 0 0 0 + diffuse 1 0 0 1 + specular 0.5 0 0 1 10 + + texture_unit + { + texture pioneerBody.jpg + filtering trilinear + } + } + pass PointLight + { + ambient 0 0 0 + diffuse 1 0 0 1 + specular 0.5 0 0 1 10 + + texture_unit + { + texture pioneerBody.jpg + filtering trilinear + } + } + + } +} + +material Gazebo/Pioneer2Body +{ + receive_shadows on + technique + { + pass + { + //ambient 0.500000 0.500000 0.500000 1.000000 + ambient 0.481193 0.000123 0.000123 1.000000 + diffuse 0.681193 0.000923 0.000923 1.000000 + specular 0.500000 0.500000 0.500000 1.000000 12.500000 + emissive 0.000000 0.000000 0.000000 1.000000 + } + } +} + +material Gazebo/Gold +{ + receive_shadows on + technique + { + pass + { + ambient 0.400000 0.248690 0.020759 1.000000 + diffuse 0.800000 0.648690 0.120759 1.000000 + specular 0.400000 0.400000 0.400000 1.000000 12.500000 + } + } +} + +material Gazebo/GreyGradientSky +{ + technique + { + pass + { + depth_write off + lighting off + + texture_unit + { + texture grey_gradient.jpg + } + } + } +} + +material Gazebo/CloudySky +{ + technique + { + pass + { + depth_write off + lighting off + + texture_unit + { + texture clouds.jpg + scroll_anim 0.15 0 + } + } + } +} + +material Gazebo/WoodPallet +{ + technique + { + pass + { + ambient 0.5 0.5 0.5 1.0 + diffuse 1.0 1.0 1.0 1.0 + specular 0.0 0.0 0.0 1.0 0.5 + + texture_unit + { + texture WoodPallet.png + filtering trilinear + } + } + } + + /* + technique + { + scheme GBuffer + pass DeferredShading/GBuffer/Pass_16 + { + lighting off + + vertex_program_ref Gazebo/NateVS + { + } + + fragment_program_ref Gazebo/NateFS + { + } + } + }*/ +} + +material Gazebo/Wood +{ + technique + { + pass + { + ambient 1.0 1.0 1.0 1.0 + diffuse 1.0 1.0 1.0 1.0 + specular 0.2 0.2 0.2 1.0 12.5 + + texture_unit + { + texture wood.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Bricks +{ + technique + { + pass + { + ambient 1.0 1.0 1.0 1.0 + diffuse 1.0 1.0 1.0 1.0 + specular 0.2 0.2 0.2 1.0 12.5 + + texture_unit + { + texture bricks.png + filtering trilinear + } + } + } +} + +material Gazebo/Road +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture road1.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Residential +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture residential.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Tertiary +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture residential.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Pedestrian +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture sidewalk.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Footway +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture sidewalk.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Motorway +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture motorway.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Lanes_6 +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture motorway.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Trunk +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture trunk.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Lanes_4 +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture trunk.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Primary +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture primary.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Lanes_2 +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture primary.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Secondary +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture secondary.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Lane_1 +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture secondary.jpg + filtering trilinear + } + } + } +} + +material Gazebo/Steps +{ + technique + { + pass + { + ambient 0.1 0.1 0.1 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.01 0.01 0.01 1.0 2.0 + + texture_unit + { + texture steps.jpeg + filtering trilinear + } + } + } +} + +material drc/san_fauxcity_sign +{ + receive_shadows off + technique + { + pass + { + ambient 0.8 0.8 0.8 1.0 + diffuse 0.8 0.8 0.8 1.0 + specular 0.1 0.1 0.1 1.0 2.0 + + texture_unit + { + texture san_fauxcity.png + filtering trilinear + } + } + } +} + +vertex_program Gazebo/GaussianCameraNoiseVS glsl +{ + source camera_noise_gaussian_vs.glsl +} + +fragment_program Gazebo/GaussianCameraNoiseFS glsl +{ + source camera_noise_gaussian_fs.glsl + default_params + { + param_named RT int 0 + param_named mean float 0.0 + param_named stddev float 1.0 + param_named offsets float3 0.0 0.0 0.0 + } +} + +material Gazebo/GaussianCameraNoise +{ + technique + { + pass + { + vertex_program_ref Gazebo/GaussianCameraNoiseVS { } + fragment_program_ref Gazebo/GaussianCameraNoiseFS { } + + texture_unit RT + { + tex_coord_set 0 + tex_address_mode clamp + filtering linear linear linear + } + } + } +} + +vertex_program Gazebo/CameraDistortionMapVS glsl +{ + source camera_distortion_map_vs.glsl +} + +fragment_program Gazebo/CameraDistortionMapFS glsl +{ + source camera_distortion_map_fs.glsl + default_params + { + param_named RT int 0 + param_named distortionMap int 1 + param_named scale float3 1.0 1.0 1.0 + } +} + +material Gazebo/CameraDistortionMap +{ + technique + { + pass + { + vertex_program_ref Gazebo/CameraDistortionMapVS { } + fragment_program_ref Gazebo/CameraDistortionMapFS { } + + texture_unit RT + { + tex_coord_set 0 + tex_address_mode border + filtering linear linear linear + } + } + } +} + +vertex_program Gazebo/WideLensMapVS glsl +{ + source wide_lens_map_vs.glsl + default_params + { + param_named ratio float 1 + } +} + +fragment_program Gazebo/WideLensMapFS glsl +{ + source wide_lens_map_fp.glsl + default_params + { + param_named envMap int 0 + param_named c1 float 1 + param_named c2 float 1 + param_named c3 float 0 + param_named f float 1 + param_named fun float3 0 0 1 + param_named cutOffAngle float 3.14 + } +} + +material Gazebo/WideLensMap +{ + technique + { + pass + { + vertex_program_ref Gazebo/WideLensMapVS { } + fragment_program_ref Gazebo/WideLensMapFS { } + } + } +} + + +vertex_program Gazebo/CameraLensFlareVS glsl +{ + source camera_lens_flare_vs.glsl +} + +fragment_program Gazebo/CameraLensFlareFS glsl +{ + source camera_lens_flare_fs.glsl + + default_params + { + param_named RT int 0 + param_named viewport float3 0.0 0.0 0.0 + param_named lightPos float3 0 0 0 + param_named scale float 1.0 + param_named color float3 1.4 1.2 1.0 + } +} + +material Gazebo/CameraLensFlare +{ + technique + { + pass + { + vertex_program_ref Gazebo/CameraLensFlareVS { } + fragment_program_ref Gazebo/CameraLensFlareFS { } + + texture_unit RT + { + tex_coord_set 0 + tex_address_mode border + filtering linear linear linear + } + } + } +} + +material Gazebo/PointCloud +{ + technique + { + pass + { + diffuse vertexcolour + specular vertexcolour + ambient vertexcolour + point_size 3 + point_sprites off + point_size_attenuation off + } + } +} + +material Gazebo/PointHandle +{ + technique + { + pass + { + lighting off + scene_blend alpha_blend + depth_write off + } + } +} + +material Gazebo/BuildingFrame +{ + technique + { + pass + { + ambient 1.0 1.0 1.0 1.0 + diffuse 1.0 1.0 1.0 1.0 + specular 0.2 0.2 0.2 1.0 12.5 + + texture_unit + { + texture building_frame.png + filtering trilinear + } + } + } +} + +material Gazebo/Runway +{ + receive_shadows on + + technique + { + pass + { + ambient 0.5 0.5 0.5 1.000000 + + texture_unit + { + texture runway.png + } + } + } +} + +material Gazebo/Grass +{ + receive_shadows on + + technique + { + pass + { + ambient 0.5 0.5 0.5 1.000000 + + texture_unit + { + scale .02 .02 + texture grass.jpg + filtering anisotropic + max_anisotropy 16 + } + } + } +} + +material Gazebo/Editor +{ + technique + { + pass ambient + { + ambient 1.0 1.0 1.0 1.0 + diffuse 1.0 1.0 1.0 1 + specular .1 .1 .1 128 + } + } +} + +material Gazebo/EditorPlane +{ + technique + { + pass + { + scene_blend colour_blend + + ambient .3 .3 .3 1.0 + diffuse .7 .7 .7 1.0 + specular 0.01 0.01 0.01 1.000000 1.500000 + } + } +} diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt index fedae18b24..96bfdfbc02 100644 --- a/test/integration/CMakeLists.txt +++ b/test/integration/CMakeLists.txt @@ -48,6 +48,7 @@ set(tests logical_camera_system.cc logical_audio_sensor_plugin.cc magnetometer_system.cc + material.cc model.cc model_photo_shoot_default_joints.cc model_photo_shoot_random_joints.cc diff --git a/test/integration/material.cc b/test/integration/material.cc new file mode 100644 index 0000000000..6d8ca1599f --- /dev/null +++ b/test/integration/material.cc @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include + +#include +#include + +#include +#include + +#include + +#include "gz/sim/EntityComponentManager.hh" +#include "gz/sim/EventManager.hh" +#include "gz/sim/Model.hh" +#include "gz/sim/SdfEntityCreator.hh" +#include "gz/sim/Server.hh" +#include "gz/sim/SystemLoader.hh" +#include "gz/sim/Types.hh" +#include "test_config.hh" + +#include "gz/sim/components/Material.hh" +#include "gz/sim/components/Model.hh" +#include "gz/sim/components/Name.hh" +#include "gz/sim/components/Visual.hh" +#include "gz/sim/components/World.hh" + +#include "../helpers/Relay.hh" +#include "../helpers/EnvTestFixture.hh" + +using namespace gz; +using namespace sim; + +class MaterialTest : public InternalFixture<::testing::Test> +{ + public: ::testing::AssertionResult StartServer( + const gz::sim::ServerConfig &_serverConfig = + gz::sim::ServerConfig()) + { + this->relay = std::make_unique(); + this->server = std::make_unique(_serverConfig); + using namespace std::chrono_literals; + this->server->SetUpdatePeriod(0ns); + + EXPECT_FALSE(this->server->Running()); + EXPECT_FALSE(*this->server->Running(0)); + // A pointer to the ecm. This will be valid once we run the mock system + relay->OnPreUpdate( + [this](const UpdateInfo &, EntityComponentManager &_ecm) + { + this->ecm = &_ecm; + }); + + this->server->AddSystem(this->relay->systemPtr); + this->server->Run(true, 1, false); + if (nullptr == this->ecm) + { + return ::testing::AssertionFailure() + << "Failed to create EntityComponentManager"; + } + + this->creator = + std::make_unique(*this->ecm, this->dummyEventMgr); + return ::testing::AssertionSuccess(); + } + + public: void SpawnModelSDF(const std::string &_sdfString) + { + ASSERT_NE(this->server, nullptr); + ASSERT_NE(this->creator, nullptr); + + sdf::Root root; + sdf::Errors errors = root.LoadSdfString(_sdfString); + EXPECT_TRUE(errors.empty()); + ASSERT_NE(nullptr, root.Model()); + + Entity modelEntity = this->creator->CreateEntities(root.Model()); + Entity worldEntity = this->ecm->EntityByComponents(components::World()); + this->creator->SetParent(modelEntity, worldEntity); + } + + public: Model GetModel(const std::string &_name) + { + return Model(this->ecm->EntityByComponents( + components::Model(), components::Name(_name))); + } + + public: std::unique_ptr relay; + public: std::unique_ptr server; + public: EntityComponentManager *ecm {nullptr}; + public: EventManager dummyEventMgr; + public: std::unique_ptr creator; +}; + +// Check for blue color parsed +TEST_F(MaterialTest, SolidColor) +{ + const std::string modelSdf = R"sdf( + + + 0 0 0.5 0 0 0 + + 0 -1.5 0 0 0 0 + + + + 1 1 1 + + + + + + + + + + )sdf"; + + ASSERT_TRUE(this->StartServer()); + this->SpawnModelSDF(modelSdf); + + auto model = this->GetModel("material_shapes"); + ASSERT_TRUE(model.Valid(*this->ecm)); + + auto boxVisualEntity = + this->ecm->EntityByComponents(components::Name("box_visual")); + ASSERT_NE(kNullEntity, boxVisualEntity); + + auto boxVisualComp = + this->ecm->Component(boxVisualEntity); + EXPECT_EQ(math::Color(0.0f, 0.0f, 1.0f, 1.0f), + boxVisualComp->Data().Ambient()); + EXPECT_EQ(math::Color(0.0f, 0.0f, 1.0f, 1.0f), + boxVisualComp->Data().Diffuse()); + EXPECT_EQ(math::Color(0.1f, 0.1f, 0.1f, 1.0f), + boxVisualComp->Data().Specular()); +} + +// Other than solid colors parsed black by default +TEST_F(MaterialTest, OtherColor) +{ + const std::string modelSdf = R"sdf( + + + 0 0 0.5 0 0 0 + + 0 -1.5 0 0 0 0 + + + + 1 1 1 + + + + + + + + + + )sdf"; + + ASSERT_TRUE(this->StartServer()); + this->SpawnModelSDF(modelSdf); + + auto model = this->GetModel("material_shapes"); + ASSERT_TRUE(model.Valid(*this->ecm)); + + auto boxVisualEntity = + this->ecm->EntityByComponents(components::Name("box_visual")); + ASSERT_NE(kNullEntity, boxVisualEntity); + + // Default to black color + auto boxVisualComp = + this->ecm->Component(boxVisualEntity); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Ambient()); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Diffuse()); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Specular()); +} + +// Warning for custom scripts not supported, default to black +TEST_F(MaterialTest, CustomScript) +{ + const std::string modelSdf = R"sdf( + + + 0 0 0.5 0 0 0 + + 0 -1.5 0 0 0 0 + + + + 1 1 1 + + + + + + + + + + )sdf"; + + ASSERT_TRUE(this->StartServer()); + this->SpawnModelSDF(modelSdf); + + auto model = this->GetModel("material_shapes"); + ASSERT_TRUE(model.Valid(*this->ecm)); + + auto boxVisualEntity = + this->ecm->EntityByComponents(components::Name("box_visual")); + ASSERT_NE(kNullEntity, boxVisualEntity); + + // Default to black color + auto boxVisualComp = + this->ecm->Component(boxVisualEntity); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Ambient()); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Diffuse()); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Specular()); +} + +// Warning for invalid name, default to black +TEST_F(MaterialTest, InvalidColor) +{ + const std::string modelSdf = R"sdf( + + + 0 0 0.5 0 0 0 + + 0 -1.5 0 0 0 0 + + + + 1 1 1 + + + + + + + + + + )sdf"; + + ASSERT_TRUE(this->StartServer()); + this->SpawnModelSDF(modelSdf); + + auto model = this->GetModel("material_shapes"); + ASSERT_TRUE(model.Valid(*this->ecm)); + + auto boxVisualEntity = + this->ecm->EntityByComponents(components::Name("box_visual")); + ASSERT_NE(kNullEntity, boxVisualEntity); + + // Default to black color + auto boxVisualComp = + this->ecm->Component(boxVisualEntity); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Ambient()); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Diffuse()); + EXPECT_EQ(math::Color(0.0f, 0.0f, 0.0f, 1.0f), + boxVisualComp->Data().Specular()); +} diff --git a/tutorials/migration_sdf.md b/tutorials/migration_sdf.md index daece419ab..4c6b618c32 100644 --- a/tutorials/migration_sdf.md +++ b/tutorials/migration_sdf.md @@ -271,8 +271,8 @@ that worked on Gazebo classic may need more plugins on Gazebo. ## Materials Gazebo does not support Ogre material files like Classic does, because Gazebo -Gazebo can be used with multiple rendering engines. Therefore, materials defined -within a `