Skip to content

Commit

Permalink
Merge pull request #977 from gazebosim/merge_7_8_20240304
Browse files Browse the repository at this point in the history
Merge 7 -> 8
  • Loading branch information
iche033 authored Mar 4, 2024
2 parents 8b92eec + 5859051 commit 79463f1
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 10 deletions.
43 changes: 33 additions & 10 deletions ogre2/src/Ogre2MeshFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,29 @@ bool Ogre2MeshFactory::LoadImpl(const MeshDescriptor &_desc)
// TODO(anyone): specular colors

// two dimensional texture coordinates
// add all texture coordinate sets
for (unsigned int k = 0u; k < subMesh.TexCoordSetCount(); ++k)
// If submesh does not have texcoord sets, add one default set.
// This is needed otherwise ogre2 will fail to generate tangents during
// Ogre::v2::Mesh::importV1() and throw an ogre exception if we try to
// apply normal maps to a submesh. Resulting object would then appear
// white without any PBR textures.
if (subMesh.TexCoordSetCount() == 0u)
{
if (subMesh.TexCoordCountBySet(k) > 0)
vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2,
Ogre::VES_TEXTURE_COORDINATES, 0);
currOffset += Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
}
// Add all texture coordinate sets
else
{
for (unsigned int k = 0u; k < subMesh.TexCoordSetCount(); ++k)
{
vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2,
Ogre::VES_TEXTURE_COORDINATES, k);
currOffset += Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
if (subMesh.TexCoordCountBySet(k) > 0)
{
vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2,
Ogre::VES_TEXTURE_COORDINATES, k);
currOffset +=
Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
}
}
}

Expand Down Expand Up @@ -436,12 +451,20 @@ bool Ogre2MeshFactory::LoadImpl(const MeshDescriptor &_desc)
}

// Add all texture coordinate sets
for (unsigned int k = 0u; k < subMesh.TexCoordSetCount(); ++k)
if (subMesh.TexCoordSetCount() == 0u)
{
*vertices++ = 0;
*vertices++ = 0;
}
else
{
if (subMesh.TexCoordCountBySet(k) > 0u)
for (unsigned int k = 0u; k < subMesh.TexCoordSetCount(); ++k)
{
*vertices++ = subMesh.TexCoordBySet(j, k).X();
*vertices++ = subMesh.TexCoordBySet(j, k).Y();
if (subMesh.TexCoordCountBySet(k) > 0u)
{
*vertices++ = subMesh.TexCoordBySet(j, k).X();
*vertices++ = subMesh.TexCoordBySet(j, k).Y();
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions test/integration/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(tests
gpu_rays
heightmap
lidar_visual
mesh
projector
render_pass
scene
Expand Down
177 changes: 177 additions & 0 deletions test/integration/mesh.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* Copyright (C) 2024 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 <gtest/gtest.h>

#include <string>
#include <memory>

#include "CommonRenderingTest.hh"

#include <gz/common/Image.hh>
#include <gz/common/Mesh.hh>
#include <gz/common/MeshManager.hh>
#include <gz/common/SubMesh.hh>

#include "gz/rendering/Camera.hh"
#include "gz/rendering/Image.hh"
#include "gz/rendering/PixelFormat.hh"
#include "gz/rendering/Scene.hh"

using namespace gz;
using namespace rendering;

class MeshTest: public CommonRenderingTest
{
};

/////////////////////////////////////////////////
TEST_F(MeshTest, NormalMapWithoutTexCoord)
{
// Create a mesh with 2 submeshes - one with red texture and the other with
// green texture. Add texcoords to the red submesh but not the green submesh.
// Verify that we can set normal map to the red submesh and the two
// submeshes should be rendered correctly

ScenePtr scene = engine->CreateScene("scene");
ASSERT_NE(nullptr, scene);
scene->SetAmbientLight(1.0, 1.0, 1.0);
scene->SetBackgroundColor(0.0, 0.0, 1.0);

VisualPtr root = scene->RootVisual();
ASSERT_NE(nullptr, root);

// create directional light
DirectionalLightPtr light0 = scene->CreateDirectionalLight();
light0->SetDirection(0.0, 0.0, -1);
light0->SetDiffuseColor(1.0, 1.0, 1.0);
light0->SetSpecularColor(1.0, 1.0, 1.0);
root->AddChild(light0);

common::Mesh mesh;
common::SubMesh subMesh0;
subMesh0.SetName("submesh0");
subMesh0.AddVertex(math::Vector3d(0, 0, 0));
subMesh0.AddVertex(math::Vector3d(1, 0, 0));
subMesh0.AddVertex(math::Vector3d(1, 1, 0));
subMesh0.AddNormal(math::Vector3d(0, 0, 1));
subMesh0.AddNormal(math::Vector3d(0, 0, 1));
subMesh0.AddNormal(math::Vector3d(0, 0, 1));
subMesh0.AddIndex(0);
subMesh0.AddIndex(1);
subMesh0.AddIndex(2);
subMesh0.AddTexCoordBySet(math::Vector2d(0, 0), 0);
subMesh0.AddTexCoordBySet(math::Vector2d(0, 1), 0);
subMesh0.AddTexCoordBySet(math::Vector2d(0, 0), 0);
common::MaterialPtr material0;
material0 = std::make_shared<common::Material>();
std::string textureMapName0 = "red_diffuse_map";
auto textureMapData0 = std::make_shared<common::Image>();
auto red = std::make_unique<unsigned char[]>(3);
red.get()[0] = 255u;
red.get()[1] = 0u;
red.get()[2] = 0u;
textureMapData0->SetFromData(red.get(), 1, 1, common::Image::RGB_INT8);
material0->SetTextureImage(textureMapName0, textureMapData0);

common::Pbr pbr;
std::string normalMapName = "normal_map";
auto normalMapData = std::make_shared<common::Image>();
auto normal = std::make_unique<unsigned char[]>(3);
normal.get()[0] = 127u;
normal.get()[1] = 127u;
normal.get()[2] = 255u;
normalMapData->SetFromData(normal.get(), 1, 1, common::Image::RGB_INT8);

pbr.SetNormalMap(normalMapName, common::NormalMapSpace::TANGENT,
normalMapData);
material0->SetPbrMaterial(pbr);
mesh.AddMaterial(material0);
subMesh0.SetMaterialIndex(0u);

common::SubMesh subMesh1;
subMesh1.SetName("submesh1");
subMesh1.AddVertex(math::Vector3d(0, 0, 0));
subMesh1.AddVertex(math::Vector3d(1, 1, 0));
subMesh1.AddVertex(math::Vector3d(0, 1, 0));
subMesh1.AddNormal(math::Vector3d(0, 0, 1));
subMesh1.AddNormal(math::Vector3d(0, 0, 1));
subMesh1.AddNormal(math::Vector3d(0, 0, 1));
subMesh1.AddIndex(0);
subMesh1.AddIndex(1);
subMesh1.AddIndex(2);

common::MaterialPtr material1;
material1 = std::make_shared<common::Material>();
std::string textureMapName1 = "green_diffuse_map";
auto textureMapData1 = std::make_shared<common::Image>();
auto green = std::make_unique<unsigned char[]>(3);
green.get()[0] = 0u;
green.get()[1] = 255u;
green.get()[2] = 0u;
textureMapData1->SetFromData(green.get(), 1, 1, common::Image::RGB_INT8);
material1->SetTextureImage(textureMapName1, textureMapData1);
mesh.AddMaterial(material1);
subMesh1.SetMaterialIndex(1u);

mesh.AddSubMesh(subMesh0);
mesh.AddSubMesh(subMesh1);

MeshDescriptor descriptor;
descriptor.meshName = "test_mesh";
descriptor.mesh = &mesh;
MeshPtr meshGeom = scene->CreateMesh(descriptor);

VisualPtr visual = scene->CreateVisual("visual");
visual->AddGeometry(meshGeom);
root->AddChild(visual);

// create camera
CameraPtr camera = scene->CreateCamera();
ASSERT_NE(nullptr, camera);
camera->SetLocalPosition(0.5, 0.5, 0.5);
camera->SetLocalRotation(0, 1.57, 0);
camera->SetImageWidth(32);
camera->SetImageHeight(32);
root->AddChild(camera);

Image image = camera->CreateImage();
camera->Capture(image);

unsigned int height = camera->ImageHeight();
unsigned int width = camera->ImageWidth();
unsigned int channelCount = PixelUtil::ChannelCount(camera->ImageFormat());
unsigned int step = width * channelCount;
unsigned char *data = image.Data<unsigned char>();
for (unsigned int i = 0; i < height; ++i)
{
for (unsigned int j = 0; j < step; j += channelCount)
{
unsigned int idx = i * step + j;
unsigned int r = data[idx];
unsigned int g = data[idx + 1];
unsigned int b = data[idx + 2];

// color should be a shade of red (submesh0) or green (submesh1)
EXPECT_TRUE(r > 0u || g > 0u);
EXPECT_EQ(b, 0u);
}
}

// Clean up
engine->DestroyScene(scene);
}

0 comments on commit 79463f1

Please sign in to comment.