Coverage Report

Created: 2025-08-29 06:18

/src/ogre/OgreMain/include/OgreShadowCameraSetupFocused.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
(Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
Copyright (c) 2006 Matthias Fink, netAllied GmbH <matthias.fink@web.de>
9
10
Permission is hereby granted, free of charge, to any person obtaining a copy
11
of this software and associated documentation files (the "Software"), to deal
12
in the Software without restriction, including without limitation the rights
13
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
copies of the Software, and to permit persons to whom the Software is
15
furnished to do so, subject to the following conditions:
16
17
The above copyright notice and this permission notice shall be included in
18
all copies or substantial portions of the Software.
19
20
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
THE SOFTWARE.
27
-----------------------------------------------------------------------------
28
*/
29
#ifndef __ShadowCameraSetupFocused_H__
30
#define __ShadowCameraSetupFocused_H__
31
32
#include "OgrePrerequisites.h"
33
#include "OgreShadowCameraSetup.h"
34
#include "OgrePolygon.h"
35
#include "OgreConvexBody.h"
36
#include "OgreHeaderPrefix.h"
37
#include "OgreAxisAlignedBox.h"
38
#include "OgreSceneNode.h"
39
40
namespace Ogre {
41
42
    /** \addtogroup Core
43
    *  @{
44
    */
45
    /** \addtogroup Scene
46
    *  @{
47
    */
48
    /** Implements the uniform shadow mapping algorithm in focused mode.
49
50
        Differs from the default shadow mapping projection in that it focuses the
51
        shadow map on the visible areas of the scene. This results in better
52
        shadow map texel usage, at the expense of some 'swimming' of the shadow
53
        texture on receivers as the basis is constantly being reevaluated.
54
55
        Original implementation by Matthias Fink <matthias.fink@web.de>, 2006.
56
    */
57
    class _OgreExport FocusedShadowCameraSetup : public DefaultShadowCameraSetup
58
    {
59
        // Persistent calculations to prevent reallocation
60
        mutable ConvexBody mBodyB;
61
        /// Use tighter focus region?
62
        bool mUseAggressiveRegion;
63
    protected:
64
        /** Transform to or from light space as defined by Wimmer et al.
65
66
            Point and spot lights need to be converted to directional lights to enable a 1:1 
67
            light mapping. Otherwise a directional light may become a point light or a point 
68
            sink (opposite of a light source) or point/spot lights may become directional lights
69
            or light sinks. The light direction is always -y.
70
        */
71
        static const Matrix4 msNormalToLightSpace;
72
        static const Matrix4 msLightSpaceToNormal;
73
74
        mutable const Camera* mLightFrustumCamera;
75
        mutable bool mLightFrustumCameraCalculated;
76
77
        /** Internal class holding a point list representation of a convex body.
78
        */
79
        class _OgreExport PointListBody
80
        {
81
            Polygon::VertexList mBodyPoints;
82
            AxisAlignedBox      mAAB;
83
84
        public:
85
            PointListBody();
86
            PointListBody(const ConvexBody& body);
87
            ~PointListBody();
88
89
            /** Merges a second PointListBody into this one.
90
            */
91
            void merge(const PointListBody& plb);
92
93
            /** Builds a point list body from a 'real' body.
94
95
                Inserts all vertices from a body into the point list with or without adding duplicate vertices.
96
            */
97
            void build(const ConvexBody& body, bool filterDuplicates = true);
98
99
            /** Builds a PointListBody from a Body and includes all the space in a given direction.
100
101
                Intersects the bounding box with a ray from each available point of the body with the given
102
                direction. Base and intersection points are stored in a PointListBody structure.
103
            @note
104
                Duplicate vertices are not filtered.
105
            @note
106
                Body is not checked for correctness.
107
            */
108
            void buildAndIncludeDirection(const ConvexBody& body, 
109
                Real extrudeDist, const Vector3& dir);
110
111
            /** Returns the bounding box representation.
112
            */
113
            const AxisAlignedBox& getAAB(void) const;   
114
115
            /** Adds a specific point to the body list.
116
            */
117
            void addPoint(const Vector3& point);
118
119
            /** Adds all points of an AAB.
120
            */
121
            void addAAB(const AxisAlignedBox& aab);
122
123
            /** Returns a point.
124
            */
125
            const Vector3& getPoint(size_t cnt) const;
126
127
            /** Returns the point count.
128
            */
129
            size_t getPointCount(void) const;
130
131
            /** Resets the body.
132
            */
133
            void reset(void);
134
135
        };
136
137
        // Persistent calculations to prevent reallocation
138
        mutable PointListBody mPointListBodyB;
139
        mutable PointListBody mPointListBodyLVS;
140
141
    protected:
142
        /** Calculates the intersection bodyB.
143
144
            The intersection bodyB consists of the concatenation the cam frustum clipped 
145
            by the scene bounding box followed by a convex hullification with the light's 
146
            position and the clipping with the scene bounding box and the light frustum:
147
            ((V \cap S) + l) \cap S \cap L (\cap: convex intersection, +: convex hull 
148
            operation).
149
            For directional lights the bodyB is assembled out of the camera frustum 
150
            clipped by the scene bounding box followed by the extrusion of all available 
151
            bodyB points towards the negative light direction. The rays are intersected 
152
            by a maximum bounding box and added to the bodyB points to form the final 
153
            intersection bodyB point list.
154
        @param sm
155
            Scene manager.
156
        @param cam
157
            Currently active camera.
158
        @param light
159
            Currently active light.
160
        @param sceneBB
161
            Scene bounding box for clipping operations.
162
        @param receiverBB
163
            Bounding information for just the receivers.
164
        @param out_bodyB
165
            Final intersection bodyB point list.
166
        */
167
        void calculateB(const SceneManager& sm, const Camera& cam, const Light& light, 
168
            const AxisAlignedBox& sceneBB, const AxisAlignedBox& receiverBB, PointListBody *out_bodyB) const;
169
170
        /** Calculates the bodyLVS.
171
172
            Calculates the bodyLVS which consists of the convex intersection operation 
173
            affecting the light frustum, the view frustum, and the current scene bounding
174
            box is used to find suitable positions in the viewer's frustum to build the 
175
            rotation matrix L_r. This matrix is applied after the projection matrix L_p to 
176
            avoid an accidental flip of the frustum orientation for views tilted with 
177
            respect to the shadow map.
178
        @param cam
179
            Current viewer camera.
180
        @param light
181
            Current light.
182
        @param sceneBB
183
            Holds all potential occluders / receivers as one single bounding box
184
            of the currently active scene node.
185
        @param out_LVS
186
            Intersection body LVS (world coordinates).
187
        */
188
        void calculateLVS(const SceneManager& sm, const Camera& cam, const Light& light,
189
            const AxisAlignedBox& sceneBB, PointListBody *out_LVS) const;
190
191
        /** Returns the projection view direction.
192
193
            After the matrix L_p is applied the orientation of the light space may tilt for
194
            non-identity projections. To prevent a false shadow cast the real view direction
195
            is evaluated and applied to the light matrix L.
196
        @param lightSpace
197
            Matrix of the light space transformation.
198
        @param cam
199
            Current viewer camera.
200
        @param bodyLVS
201
            Intersection body LVS (relevant space in front of the camera).
202
        */
203
        Vector3 getLSProjViewDir(const Matrix4& lightSpace, const Camera& cam, 
204
            const PointListBody& bodyLVS) const;
205
206
        /** Returns a valid near-point seen by the camera.
207
208
            Returns a point that is situated near the camera by analyzing the bodyLVS that
209
            contains all the relevant scene space in front of the light and the camera in
210
            a point list array. The view matrix is relevant because the nearest point in
211
            front of the camera should be determined.
212
        @param viewMatrix
213
            View matrix of the current camera.
214
        @param bodyLVS
215
            Intersection body LVS (relevant space in front of the camera).
216
        */
217
        Vector3 getNearCameraPoint_ws(const Affine3& viewMatrix,
218
            const PointListBody& bodyLVS) const;
219
220
        /** Transforms a given body to the unit cube (-1,-1,-1) / (+1,+1,+1) with a specific 
221
            shadow matrix enabled.
222
223
            Transforms a given point list body object with the matrix m and then maps its
224
            extends to a (-1,-1,-1) / (+1,+1,+1) unit cube.
225
        @param m
226
            Transformation matrix applied on the point list body.
227
        @param body 
228
            Contains the points of the extends of all valid scene elements which 
229
            are mapped to the unit cube.
230
        */
231
        Matrix4 transformToUnitCube(const Matrix4& m, const PointListBody& body) const;
232
    public:
233
        /// @deprecated use create()
234
        FocusedShadowCameraSetup(bool useAggressiveRegion = true);
235
236
        ~FocusedShadowCameraSetup();
237
238
        /** Create an instance
239
240
            There are 2 approaches that can  be used to define the focus region,
241
            the more aggressive way introduced by Wimmer et al, or the original
242
            way as described in Stamminger et al. Wimmer et al's way tends to
243
            come up with a tighter focus region but in rare cases (mostly highly
244
            glancing angles) can cause some shadow casters to be clipped
245
            incorrectly. By default the more aggressive approach is used since it
246
            leads to significantly better results in most cases, but if you experience
247
            clipping issues, you can use the less aggressive version.
248
        @param useAggressiveRegion
249
            True to use the more aggressive approach, false otherwise.
250
         */
251
        static ShadowCameraSetupPtr create(bool useAggressiveRegion = true)
252
0
        {
253
0
            return std::make_shared<FocusedShadowCameraSetup>(useAggressiveRegion);
254
0
        }
255
256
        /** Returns a uniform shadow camera with a focused view.
257
        */
258
        void getShadowCamera(const SceneManager *sm, const Camera *cam,
259
            const Viewport *vp, const Light *light, Camera *texCam, size_t iteration) const override;
260
261
        /** Sets whether or not to use the more aggressive approach to deciding on
262
            the focus region or not.
263
        */
264
0
        void setUseAggressiveFocusRegion(bool aggressive) { mUseAggressiveRegion = aggressive; }
265
266
0
        bool getUseAggressiveFocusRegion() const { return mUseAggressiveRegion; }
267
268
    };
269
270
    /** @} */
271
    /** @} */
272
273
} // namespace Ogre
274
275
#include "OgreHeaderSuffix.h"
276
277
#endif // __ShadowCameraSetupFocused_H__