Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix setting normal map when not all submeshes have texcoords (ogre2) #976

Merged
merged 3 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions ogre2/src/Ogre2MeshFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -382,13 +382,22 @@ bool Ogre2MeshFactory::LoadImpl(const MeshDescriptor &_desc)

// two dimensional texture coordinates
// add all texture coordinate sets
for (unsigned int k = 0u; k < subMesh.TexCoordSetCount(); ++k)
if (subMesh.TexCoordSetCount() == 0u)
iche033 marked this conversation as resolved.
Show resolved Hide resolved
{
if (subMesh.TexCoordCountBySet(k) > 0)
{
vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2,
Ogre::VES_TEXTURE_COORDINATES, k);
Ogre::VES_TEXTURE_COORDINATES, 0);
currOffset += Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
}
else
{
for (unsigned int k = 0u; k < subMesh.TexCoordSetCount(); ++k)
{
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 +445,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;
shameekganguly marked this conversation as resolved.
Show resolved Hide resolved
*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] = 255;
red.get()[1] = 0;
red.get()[2] = 0;
iche033 marked this conversation as resolved.
Show resolved Hide resolved
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] = 127;
normal.get()[1] = 127;
normal.get()[2] = 255;
iche033 marked this conversation as resolved.
Show resolved Hide resolved
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] = 0;
green.get()[1] = 255;
green.get()[2] = 0;
iche033 marked this conversation as resolved.
Show resolved Hide resolved
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);
}
Loading