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

Add Ogre2Heightmap functionality #386

Merged
merged 107 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from 101 commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
025f72a
Ogre2.2
ahcorde Mar 23, 2021
1cff215
Added media files
ahcorde Mar 23, 2021
e5979b8
Added Headless mode
ahcorde Mar 23, 2021
fc89bef
Added feedback
ahcorde Mar 23, 2021
c5c077c
Added feedback
ahcorde Mar 24, 2021
8033623
Add OGRE2.2 to dependencies
mjcarroll Mar 24, 2021
a82820c
Fixed GPUray and depthCamera test
ahcorde Mar 24, 2021
b5c639e
Merge branch 'main' into ahcorde/update/ogre2.2
ahcorde Mar 24, 2021
b664ade
cast based on pf
iche033 Mar 25, 2021
d6808b8
Fix cleanup with packaged debs
mjcarroll Mar 25, 2021
e940e9a
fix copy raw data
iche033 Mar 25, 2021
92e8fbf
Merge branch 'ahcorde/update/ogre2.2' of github.com:ignitionrobotics/…
iche033 Mar 25, 2021
11cd876
fix material test
iche033 Mar 25, 2021
88cfd40
Lint and compiler warning
mjcarroll Mar 25, 2021
db609f3
Trim whitespace
mjcarroll Mar 25, 2021
bc12f40
Apply gamma correction to sky
ahcorde Mar 25, 2021
fcf51b1
Merge branch 'ahcorde/update/ogre2.2' of https://github.com/ignitionr…
ahcorde Mar 25, 2021
797675b
Test fixes to Ogre2.2 branch (#279)
mjcarroll Mar 25, 2021
7046608
Merge branch 'main' into ahcorde/update/ogre2.2
ahcorde Mar 25, 2021
d55ee47
Revert gamma correction in the sky
ahcorde Mar 25, 2021
01aeec2
Merge branch 'main' into ahcorde/update/ogre2.2
iche033 Apr 13, 2021
62bb629
enable grayscale albedo map to fix red color highlights and disable h…
iche033 Apr 14, 2021
032ce0f
Merge branch 'main' into ahcorde/update/ogre2.2
mjcarroll May 4, 2021
adfdb05
Local updates for Ogre2.2 against main branch (#317)
mjcarroll May 5, 2021
24fb7df
Fix merge
ahcorde May 11, 2021
72f23ab
Merge branch 'main' into ahcorde/update/ogre2.2
iche033 May 11, 2021
96b2eb5
fix shadows in ogre 2.2
iche033 May 11, 2021
5e2f7b5
Merge branch 'main' into ahcorde/update/ogre2.2
mjcarroll May 18, 2021
21b5993
Merge branch 'main' into ahcorde/update/ogre2.2
mjcarroll May 24, 2021
c2bbbe9
Lint
mjcarroll May 24, 2021
2e9d62e
fix toggling sky
iche033 Jun 8, 2021
b37ab76
fix camera test
iche033 Jun 8, 2021
523a5cc
Merge remote-tracking branch 'origin/main' into ahcorde/update/ogre2.2
ahcorde Jun 10, 2021
0df4dd4
make linters happy
ahcorde Jun 10, 2021
b9e8032
make linters happy
ahcorde Jun 10, 2021
5d1bbb6
Merge branch 'main' into ahcorde/update/ogre2.2
mjcarroll Jun 16, 2021
24a67ad
Fix small regression from merge
mjcarroll Jun 20, 2021
9a381e2
Remove problematic leftover files from 2.1
darksylinc Jun 27, 2021
175fcae
Do not crash on shutdown
darksylinc Jun 27, 2021
fb0fb6e
Remove problematic leftover files from 2.1 (#354)
darksylinc Jun 28, 2021
7816937
Do not crash on shutdown (#355)
darksylinc Jun 28, 2021
970d862
Removed unused variable
ahcorde Jun 29, 2021
9f15486
Merge branch 'main' into matias-ogre2.2-main-merge
darksylinc Jul 3, 2021
d3adfbe
Restore FSAA support in 2.2 branch
darksylinc Jul 3, 2021
31b4960
Fix changing background color not always taking immediate effect
darksylinc Jul 3, 2021
60391e1
Changed pass_clear in favour of LoadAction::Clear
darksylinc Jul 3, 2021
d93cc18
Missing public keyword
darksylinc Jul 3, 2021
8c2ec12
Save VRAM when FSAA is used and no postprocessing
darksylinc Jul 3, 2021
84513fa
Merge branch 'ahcorde/update/ogre2.2' into matias-ogre2.2-main-merge
darksylinc Jul 3, 2021
029cd59
Remove code deprecated in ign-rendering5
darksylinc Jul 5, 2021
f951593
Remove code deprecated in ign-rendering5
darksylinc Jul 5, 2021
34c31d0
Code style fixes
darksylinc Jul 10, 2021
c19ec56
Undo VRAM saving optimization: It cannot be applied
darksylinc Jul 10, 2021
d3ce87d
Merge main branch into Ogre 2.2 and fixes (#359)
darksylinc Jul 13, 2021
c07bf60
Began work on Heightmaps with Ogre2. Very WIP
darksylinc Aug 1, 2021
22bc5c1
Register HlmsTerra
darksylinc Aug 1, 2021
8480e71
Update all Terras and show them on screen (WIP)
darksylinc Aug 8, 2021
2e75b61
Update to latest Terra to get Z-up support
darksylinc Aug 8, 2021
fe97c66
Better calculation of heightmap size (WIP)
darksylinc Aug 9, 2021
5f53934
Merge remote-tracking branch 'origin/main' into ahcorde/update/ogre2.2
ahcorde Aug 12, 2021
0818a0f
Merge branch 'main' into ahcorde/update/ogre2.2
ahcorde Aug 19, 2021
aacbdcc
Fix shader compiler error
darksylinc Aug 9, 2021
83e8567
Fix alignment issues in terrain
darksylinc Aug 14, 2021
a714833
Move Terra to its own folder and project
darksylinc Aug 14, 2021
ed8fc4e
Enable assert that was accidentally disabled
darksylinc Aug 14, 2021
74a6d5d
Customize Terra for Ignition's requirements
darksylinc Aug 15, 2021
835c559
Use custom blending modes to adjust to ign
darksylinc Aug 15, 2021
b88ff85
HeightmapTexture::Size is in meters, it's not a scale
darksylinc Aug 15, 2021
6cc6f9a
Use same blending algorithm for roughness & metalness
darksylinc Aug 15, 2021
cd3a095
Deal with edge case where terrain skirts could be above ground
darksylinc Aug 15, 2021
872caf6
Fix wrong indentation
darksylinc Aug 15, 2021
343268d
Forgot to push this change
darksylinc Aug 16, 2021
e17406e
Disable alpha blending of detail maps for Terrain
darksylinc Aug 21, 2021
44b3a6f
Add terrain shadows to normal objects
darksylinc Aug 21, 2021
3f3f372
Merge branch 'ahcorde/update/ogre2.2' into matias-ogre22-terra
darksylinc Aug 25, 2021
b295710
Fix copyright year
darksylinc Aug 25, 2021
9e4243d
Re-enable ImageHeightmap
darksylinc Aug 28, 2021
fcf3315
Cosmetic changes
darksylinc Aug 28, 2021
1b1ab13
Move Terra's source code into ogre2/src
darksylinc Aug 28, 2021
84f5b1b
Support ogre1 heightmaps via cropping and warn about it
darksylinc Aug 28, 2021
82bdd43
Support both ogre2 & ogre engines in heightmap sample
darksylinc Aug 28, 2021
147232f
Force-disable JSON parts of Terra
darksylinc Aug 28, 2021
66f59c1
Add license to Terra files
darksylinc Aug 28, 2021
7d22d26
Update to latest version of Terra
darksylinc Aug 28, 2021
38c74c7
Add terrain shadows from spot & point lights
darksylinc Aug 28, 2021
373fd9d
Skip Terra headers in cppcheck
darksylinc Aug 30, 2021
f53d5db
fixing tests
iche033 Sep 2, 2021
0d1999e
add ifdef
iche033 Sep 3, 2021
588100c
suppress warnings
iche033 Sep 3, 2021
20e24e9
update syntax
iche033 Sep 3, 2021
93599aa
update syntax
iche033 Sep 3, 2021
be61509
Merge branch 'main' into ahcorde/update/ogre2.2
iche033 Sep 3, 2021
baf8cff
Merge branch 'ahcorde/update/ogre2.2' into matias-ogre22-terra
darksylinc Sep 4, 2021
4c08baa
Fix crash on shutdown due to ptr destroyed too late
darksylinc Sep 4, 2021
1fb65fc
Update to latest Terra to fix bug from upstream
darksylinc Sep 7, 2021
b75531c
Merge branch 'main' into matias-ogre22-terra
darksylinc Sep 9, 2021
226ecaf
Update to latest Hlms from upstream
darksylinc Sep 9, 2021
93d88e1
Merge branch 'main' into matias-ogre22-terra
iche033 Sep 11, 2021
24d957a
Fix compiler warning
darksylinc Sep 11, 2021
27ea80e
Fix Terra shadows on Spot and Point lights
darksylinc Sep 11, 2021
383d80e
Fix Terra's point light shadows
darksylinc Sep 11, 2021
6715cbb
Fix documentation
darksylinc Sep 15, 2021
260255b
Merge branch 'main' into matias-ogre22-terra
iche033 Sep 16, 2021
6894fd3
fixing CI
iche033 Sep 16, 2021
19d922c
add include path
iche033 Sep 16, 2021
c9d5a17
windows warning
iche033 Sep 16, 2021
bb0119b
fix
iche033 Sep 16, 2021
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
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,18 @@ if (HAVE_OGRE2)
list(APPEND RENDERING_COMPONENTS ogre2)
endif()

configure_file("${PROJECT_SOURCE_DIR}/cppcheck.suppress.in"
${PROJECT_BINARY_DIR}/cppcheck.suppress)

ign_configure_build(QUIT_IF_BUILD_ERRORS
COMPONENTS ${RENDERING_COMPONENTS})

if (HAVE_OGRE2)
# Must be done after ign_configure_build or else Terra
# won't see IGN_ADD_fPIC_TO_LIBRARIES
add_subdirectory(ogre2/src/terrain/Terra)
endif()

#============================================================================
# Create package information
#============================================================================
Expand Down
1 change: 1 addition & 0 deletions cppcheck.suppress.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*:*/Terra/*.h
14 changes: 11 additions & 3 deletions examples/heightmap/Main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ void buildScene(ScenePtr _scene)
CameraPtr camera = _scene->CreateCamera("camera");
camera->SetLocalPosition(1.441, 25.787, 17.801);
camera->SetLocalRotation(0.0, 0.588, -1.125);
camera->SetImageWidth(800);
camera->SetImageHeight(600);
camera->SetImageWidth(1600);
camera->SetImageHeight(900);
camera->SetAntiAliasing(2);
camera->SetAspectRatio(1.333);
camera->SetHFOV(IGN_PI / 2);
Expand Down Expand Up @@ -207,7 +207,15 @@ int main(int _argc, char** _argv)
std::vector<std::string> engineNames;
std::vector<CameraPtr> cameras;

engineNames.push_back("ogre");
// Expose engine name to command line because we can't instantiate both
// ogre and ogre2 at the same time
std::string ogreEngineName("ogre2");
if (_argc > 1)
{
ogreEngineName = _argv[1];
}

engineNames.push_back(ogreEngineName);

for (auto engineName : engineNames)
{
Expand Down
108 changes: 108 additions & 0 deletions ogre2/include/ignition/rendering/ogre2/Ogre2Heightmap.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (C) 2021 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 IGNITION_RENDERING_OGRE2_OGRE2HEIGHTMAP_HH_
#define IGNITION_RENDERING_OGRE2_OGRE2HEIGHTMAP_HH_

#include <memory>

#include "ignition/rendering/base/BaseHeightmap.hh"
#include "ignition/rendering/ogre2/Ogre2Geometry.hh"

// Ignoring warning: "non dll-interface class
// 'ignition::rendering::v5::Heightmap' used as base for dll-interface class"
// because `Heightmap` and `BaseHeightmap` are header-only
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4275)
#endif

namespace Ogre
{
class Camera;
class Terra;
}

namespace ignition
{
namespace rendering
{
inline namespace IGNITION_RENDERING_VERSION_NAMESPACE {
//
// Forward declaration
class Ogre2HeightmapPrivate;

/// \brief Ogre implementation of a heightmap geometry.
class IGNITION_RENDERING_OGRE2_VISIBLE Ogre2Heightmap
: public BaseHeightmap<Ogre2Geometry>
{
/// \brief Constructor
/// \param[in]
public: explicit Ogre2Heightmap(const HeightmapDescriptor &_desc);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public: explicit Ogre2Heightmap(const HeightmapDescriptor &_desc);
\param[in]
public: explicit Ogre2Heightmap(const HeightmapDescriptor &_desc);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the new version ok?

I can't describe HeightmapDescriptor because I didn't write it.

This is a copy paste from OgreHeightmap.hh

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like Parameters that describe how a heightmap should be loaded. should suffice.

this is needed to fix: https://github.com/ignitionrobotics/ign-rendering/pull/386/checks?check_run_id=3576496054


/// \brief Destructor
public: virtual ~Ogre2Heightmap() override;

// Documentation inherited.
public: virtual void Init() override;

// Documentation inherited.
public: virtual void PreRender() override;

/// \brief Returns NULL, heightmaps don't have movable objects.
/// \return Null pointer.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always return Null ?

Suggested change
/// \return Null pointer.
/// \return Null pointer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true in ogre 1.x but looking at the Ogre2Heightmap::OgreObject() implementation, it returns an Ogre::Terra object. Can you update the comment here @darksylinc ?

public: virtual Ogre::MovableObject *OgreObject() const override;

/// \brief Returns NULL, heightmap materials don't inherit from
/// MaterialPtr.
/// \return Null pointer.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always return Null ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, looks like still always returns null. Textures are specified through HeightmapDescriptor

public: virtual MaterialPtr Material() const override;

/// \brief Has no effect for heightmaps. The material is set through a
/// HeightmapDescriptor.
/// \param[in] _material Not used.
/// \param[in] _unique Not used.
public: virtual void SetMaterial(MaterialPtr _material, bool _unique)
override;

/// \internal
/// \brief Retrieves the internal Terra pointer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// \brief Retrieves the internal Terra pointer
\return ...
/// \brief Retrieves the internal Terra pointer

/// \return internal Terra pointer
public: Ogre::Terra* Terra();

/// \internal
/// \brief Must be called before rendering with the camera
/// that will perform rendering.
///
/// May update shadows if light direction changed
/// \param[in] _camera Camera about to be used for rendering
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// \param[in] _camera Camera about to be used for rendering
/// \param[in] _activeCamera Camera about to be used for rendering

public: void UpdateForRender(Ogre::Camera *_activeCamera);

/// \brief Heightmap should only be created by scene.
private: friend class OgreScene;

/// \brief Private data class
private: std::unique_ptr<Ogre2HeightmapPrivate> dataPtr;
};
}
}
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif
22 changes: 22 additions & 0 deletions ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ namespace Ogre
{
class OverlaySystem;
}

class HlmsPbsTerraShadows;
class CompositorWorkspaceListener;
}

namespace ignition
Expand Down Expand Up @@ -175,6 +178,25 @@ namespace ignition
/// \return Pointer to the ogre overlay system.
public: Ogre::v1::OverlaySystem *OverlaySystem() const;

/// \internal
/// \brief Get a pointer to the Pbs listener that adds terra shadows.
/// Do NOT assume HlmsPbs::getListener() == HlmsPbsTerraShadows()
/// as there may be more than one listener in the future with
/// a master listener coordinating them
/// \return Pointer to the Pbs listener that adds terra shadows.
public: Ogre::HlmsPbsTerraShadows *HlmsPbsTerraShadows() const;

/// \internal
/// \brief Get a pointer to the workspace listener that adds terra
/// casting shadows from spot and point lights.
///
/// This listener needs to be added to each workspace that wants
/// terrain shadows from spot/point lights. If no terrains are in scene
/// then the workspace's overhead is negligible / almost 0.
/// \return Pointer to the CompositorWorkspaceListener
public: Ogre::CompositorWorkspaceListener
*TerraWorkspaceListener() const;

/// \brief Pointer to the ogre's overlay system
private: Ogre::v1::OverlaySystem *ogreOverlaySystem = nullptr;

Expand Down
2 changes: 2 additions & 0 deletions ogre2/include/ignition/rendering/ogre2/Ogre2RenderTypes.hh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace ignition
class Ogre2GizmoVisual;
class Ogre2GpuRays;
class Ogre2Grid;
class Ogre2Heightmap;
class Ogre2InertiaVisual;
class Ogre2JointVisual;
class Ogre2Light;
Expand Down Expand Up @@ -87,6 +88,7 @@ namespace ignition
typedef shared_ptr<Ogre2GizmoVisual> Ogre2GizmoVisualPtr;
typedef shared_ptr<Ogre2GpuRays> Ogre2GpuRaysPtr;
typedef shared_ptr<Ogre2Grid> Ogre2GridPtr;
typedef shared_ptr<Ogre2Heightmap> Ogre2HeightmapPtr;
typedef shared_ptr<Ogre2InertiaVisual> Ogre2InertiaVisualPtr;
typedef shared_ptr<Ogre2JointVisual> Ogre2JointVisualPtr;
typedef shared_ptr<Ogre2Light> Ogre2LightPtr;
Expand Down
17 changes: 16 additions & 1 deletion ogre2/include/ignition/rendering/ogre2/Ogre2Scene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <memory>
#include <string>
#include <vector>

#include "ignition/rendering/Storage.hh"
#include "ignition/rendering/base/BaseScene.hh"
Expand Down Expand Up @@ -135,7 +136,12 @@ namespace ignition
/// \brief When LegacyAutoGpuFlush(), this function mimics
/// legacy behavior.
/// When not, it verifies PreRender has been called
public: void StartRendering();
/// It also performs necessary updates for all heightmaps
///
/// \param _camera camera that is about to render, used
/// by heightmaps (Terra). See Ogre2Scene::UpdateAllHeightmaps
/// Can be null
public: void StartRendering(Ogre::Camera *_camera);

/// \internal
/// \brief Every Render() function calls this function with
Expand Down Expand Up @@ -334,6 +340,12 @@ namespace ignition
protected: virtual bool InitObject(Ogre2ObjectPtr _object,
unsigned int _id, const std::string &_name);

/// \internal
/// \brief Iterates through all Heightmaps and calls
/// Ogre2Heightmap::UpdateForRender on each of them
/// \param[in] _camera Camera about to be used for rendering
public: void UpdateAllHeightmaps(Ogre::Camera *_camera);

/// \brief Create a compositor shadow node with the same number of shadow
/// textures as the number of shadow casting lights
protected: void UpdateShadowNode();
Expand Down Expand Up @@ -405,6 +417,9 @@ namespace ignition
/// \brief A list of ogre materials
protected: Ogre2MaterialMapPtr materials;

/// \brief A list of ogre heightmaps
protected: std::vector<std::weak_ptr<Ogre2Heightmap>> heightmaps;

/// \brief Pointer to the ogre scene manager
protected: Ogre::SceneManager *ogreSceneManager = nullptr;

Expand Down
1 change: 1 addition & 0 deletions ogre2/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ target_link_libraries(${ogre2_target}
PRIVATE
ignition-plugin${IGN_PLUGIN_VER}::register
${OPENGL_LIBRARIES}
terra
IgnOGRE2::IgnOGRE2)

set (versioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX})
Expand Down
5 changes: 4 additions & 1 deletion ogre2/src/Ogre2DepthCamera.cc
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,9 @@ void Ogre2DepthCamera::CreateWorkspaceInstance()
this->dataPtr->ogreCompositorWorkspaceDef,
false);

this->dataPtr->ogreCompositorWorkspace->addListener(
engine->TerraWorkspaceListener());

// add the listener
Ogre::CompositorNode *node =
this->dataPtr->ogreCompositorWorkspace->getNodeSequence()[0];
Expand Down Expand Up @@ -958,7 +961,7 @@ void Ogre2DepthCamera::Render()
glEnable(GL_DEPTH_CLAMP);
#endif

this->scene->StartRendering();
this->scene->StartRendering(this->ogreCamera);

// update the compositors
this->dataPtr->ogreCompositorWorkspace->_validateFinalTarget();
Expand Down
3 changes: 2 additions & 1 deletion ogre2/src/Ogre2GpuRays.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,7 @@ void Ogre2GpuRays::UpdateRenderTarget1stPass()
// update the compositors
for (auto i : this->dataPtr->cubeFaceIdx)
{
this->scene->UpdateAllHeightmaps(this->dataPtr->cubeCam[i]);
this->dataPtr->ogreCompositorWorkspace1st[i]->setEnabled(true);

this->dataPtr->ogreCompositorWorkspace1st[i]->_validateFinalTarget();
Expand Down Expand Up @@ -1234,7 +1235,7 @@ void Ogre2GpuRays::UpdateRenderTarget2ndPass()
//////////////////////////////////////////////////
void Ogre2GpuRays::Render()
{
this->scene->StartRendering();
this->scene->StartRendering(nullptr);

this->UpdateRenderTarget1stPass();
this->UpdateRenderTarget2ndPass();
Expand Down
Loading