]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/meshtex/MeshEntity.h
Radiant:
[xonotic/netradiant.git] / contrib / meshtex / MeshEntity.h
1 /**
2  * @file MeshEntity.h
3  * Declares the MeshEntity class.
4  * @ingroup meshtex-core
5  */
6
7 /*
8  * Copyright 2012 Joel Baxter
9  *
10  * This file is part of MeshTex.
11  *
12  * MeshTex is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * MeshTex is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with MeshTex.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #if !defined(INCLUDED_MESHENTITY_H)
27 #define INCLUDED_MESHENTITY_H
28
29 #include "AllocatedMatrix.h"
30
31 #include "scenelib.h"
32 #include "ipatch.h"
33 #include "generic/callback.h"
34
35 /**
36  * Wrapper for a biquadratic Bezier patch mesh entity from Radiant.
37  * Instantiate this for a given patch mesh, then use the methods to
38  * interrogate or modify the mesh. It is intended that this object be
39  * instantiated, used, and then discarded before resuming other Radiant
40  * operations, as the implementation assumes that several basic mesh
41  * characteristics will remain constant for the life of this object.
42  *
43  * @ingroup meshtex-core
44  */
45 class MeshEntity
46 {
47 public: // public types
48
49    /**
50     * Values that represent the texture axes an operation should manipulate.
51     */
52    enum TextureAxisSelection
53    {
54       S_TEX_AXIS_ONLY,  ///< manipulate the S values
55       T_TEX_AXIS_ONLY,  ///< manipulate the T values
56       ALL_TEX_AXES      ///< manipulate both S and T values
57    };
58
59    /**
60     * Values that represent the kinds of patch mesh slices. Note that the
61     * assigned integer values are significant; do not change.
62     */
63    enum SliceType
64    {
65       ROW_SLICE_TYPE = 0,  ///< row 
66       COL_SLICE_TYPE = 1,  ///< column 
67       NUM_SLICE_TYPES = 2  ///< number of kinds of slice 
68    };
69
70    /**
71     * Type for info/warning/error callbacks. The callback takes a const
72     * char* argument (the message string); it has no return value.
73     */
74    typedef Callback1<const char *, void> MessageCallback;
75
76    /**
77     * Type for texture scale info callbacks. The callback takes two float
78     * arguments (scale and tiles); it has no return value.
79     */
80    typedef Callback2<float, float, void> TexInfoCallback;
81
82    /**
83     * Type for defining how to manipulate control point or surface values
84     * according to some linear combination of various values.
85     */
86    typedef struct {
87       float oldValue;     ///< coefficient for original value
88       float rowDistance;  ///< coefficient for surface distance along row
89       float colDistance;  ///< coefficient for surface distance along col
90       float rowNumber;    ///< coefficient for row number
91       float colNumber;    ///< coefficient for column number
92       float constant;     ///< constant
93    } GeneralFunctionFactors;
94
95    /**
96     * Type for choosing a particular slice of a known kind (row or column).
97     */
98    typedef struct {
99       bool maxSlice;  ///< if true, choose slice with highest index
100       int index;      ///< if maxSlice is false, choose slice with this index
101    } SliceDesignation;
102
103    /**
104     * Type for choosing a reference slice of a known kind (row or column) and
105     * indicating how to use it for reference. Reference can be made to the total
106     * slice surface length alone, or to each individual control point.
107     */
108    typedef struct {
109       SliceDesignation designation;  ///< the slice
110       bool totalLengthOnly;          ///< if true, reference total length only
111    } RefSliceDescriptor;
112
113    /**
114     * An instance of this class can be used as a MeshEntity::TexInfoCallback, in
115     * situations where the callback is a method to be invoked on a target
116     * object. When invoking this constructor, the target object is the
117     * constructor argument, and the target object class and method are template
118     * parameters. The target object's method must have an appropriate signature
119     * for TexInfoCallback: two float arguments, void return.
120     */
121    template<typename ObjectClass, void (ObjectClass::*member)(float, float)>
122    class TexInfoCallbackMethod :
123       public BindFirstOpaque2<Member2<ObjectClass, float, float, void, member> >
124    {
125    public:
126       /**
127        * Constructor.
128        *
129        * @param object The object on which to invoke the callback method.
130        */
131       TexInfoCallbackMethod(ObjectClass& object) :
132          BindFirstOpaque2<Member2<ObjectClass, float, float, void, member> >(object) {}
133    };
134
135 public: // public methods
136
137    /// @name Lifecycle
138    //@{
139    MeshEntity(scene::Node& mesh,
140               const MessageCallback& infoReportCallback,
141               const MessageCallback& warningReportCallback,
142               const MessageCallback& errorReportCallback);
143    ~MeshEntity();
144    //@}
145    /// @name Interrogation
146    //@{
147    bool IsValid() const;
148    void GetInfo(const int *refRow,
149                 const int *refCol,
150                 const TexInfoCallback *rowTexInfoCallback,
151                 const TexInfoCallback *colTexInfoCallback);
152    //@}
153    /// @name Simple modification
154    //@{
155    void MinAlign(TextureAxisSelection axes);
156    void MaxAlign(TextureAxisSelection axes);
157    void MinMaxAlignAutoScale(TextureAxisSelection axes);
158    void MinMaxAlignStretch(TextureAxisSelection axes);
159    void MinMaxAlignShrink(TextureAxisSelection axes);
160    //@}
161    /// @name Complex modification
162    //@{
163    void SetScale(SliceType sliceType,
164                  const SliceDesignation *alignSlice,
165                  const RefSliceDescriptor *refSlice,
166                  bool naturalScale,
167                  float naturalScaleOrTiles);
168    void GeneralFunction(const GeneralFunctionFactors *sFactors,
169                         const GeneralFunctionFactors *tFactors,
170                         const SliceDesignation *alignRow,
171                         const SliceDesignation *alignCol,
172                         const RefSliceDescriptor *refRow,
173                         const RefSliceDescriptor *refCol,
174                         bool surfaceValues);
175    //@}
176
177 private: // private methods
178
179    /// @name Unimplemented to prevent copy/assignment
180    //@{
181    MeshEntity(const MeshEntity&);
182    const MeshEntity& operator=(const MeshEntity&);
183    //@}
184
185 private: // private types
186
187    /**
188     * Values that represent the kinds of texture axis.
189     */
190    enum TextureAxis
191    {
192       S_TEX_AXIS = 0,   ///< S texture axis 
193       T_TEX_AXIS = 1,   ///< T texture axis
194       NUM_TEX_AXES = 2  ///< number of kinds of texture axis
195    };
196
197    /**
198     * Values that represent the kinds of position (spatial) axis.
199     */
200    enum PositionAxis
201    {
202       X_POS_AXIS = 0,   ///< X position axis 
203       Y_POS_AXIS = 1,   ///< Y position axis
204       Z_POS_AXIS = 2,   ///< Z position axis
205       NUM_POS_AXES = 3  ///< number of kinds of position axis
206    };
207
208    /**
209     * Values that represent ways of scaling a texture to make it aligned.
210     */
211    enum ScaleOperation
212    {
213       STRETCH_SCALE_OP,  ///< scale by stretching
214       SHRINK_SCALE_OP    ///< scale by shrinking
215    };
216
217    /**
218     * Type for orienting a slice within a particular patch.
219     */
220    typedef struct {
221       SliceType sliceType; ///< slice type (row or column)
222       float position;      ///< fractional dist from patch edge (0, 0.5, or 1)
223       int edgeSlice[NUM_SLICE_TYPES];  ///< indices of slices at patch edges
224    } SlicePatchContext;
225
226    /**
227     * Type for describing the application of a texture along a given slice,
228     * on a specified texture axis.
229     */
230    typedef struct {
231       float scale;  ///< texture scale along axis
232       float tiles;  ///< # of times the texture tiles along axis
233       float min;    ///< minimum value for that texture axis
234       float max;    ///< maximum value for that texture axis
235    } SliceTexInfo;
236
237    /**
238     * Type for internal representation of a reference slice of a given kind
239     * (row or column), specifying the slice and indicating how to use it for
240     * reference. Any external specification of "max slice" has been replaced
241     * with an explicit slice number. Reference can be made to the total slice
242     * length alone, or to the distance to each individual control point.
243     */
244    typedef struct {
245       unsigned index;        ///< choose slice with this number
246       bool totalLengthOnly;  ///< if true, reference total length only
247    } RefSliceDescriptorInt;
248
249    /**
250     * Function signature for a private method that applies a preset
251     * transformation on a given texture axis.
252     */
253    typedef bool(MeshEntity::*InternalImpl)(TextureAxis axis);
254
255 private: // private template methods
256
257    /**
258     * Utility template function for accessing a matrix element from code that
259     * operates on either kind of slice.
260     *
261     * @param matrix    The matrix holding the mesh control points.
262     * @param sliceType Slice kind (row or column).
263     * @param slice     Slice number, among slices of that type in mesh.
264     * @param index     Element index along the slice.
265     *
266     * @return The matrix element; can be used as lvalue or rvalue.
267     */
268    template<typename Element>
269    inline static Element& MatrixElement(Matrix<Element>& matrix,
270                                         SliceType sliceType,
271                                         int slice,
272                                         int index) {
273       return (sliceType == ROW_SLICE_TYPE ? matrix(slice, index) : 
274                                             matrix(index, slice));
275    }
276
277 private: // private methods
278
279    /// @name Internal state refresh
280    //@{
281    void UpdatePosMinMax(PositionAxis axis);
282    void UpdateTexMinMax(TextureAxis axis);
283    //@}
284    /// @name Radiant state management
285    //@{
286    void CreateUndoPoint();
287    void CommitChanges();
288    //@}
289    /// @name Argument resolution
290    //@{
291    int InternalSliceDesignation(const SliceDesignation *sliceDesignation,
292                                 SliceType sliceType);
293    RefSliceDescriptorInt *InternalRefSliceDescriptor(const RefSliceDescriptor *refSlice,
294                                                      SliceType sliceType,
295                                                      RefSliceDescriptorInt& refSliceInt);
296    //@}
297    /// @name Subroutines for interrogation
298    //@{
299    float GetSliceTexScale(SliceType sliceType,
300                           int slice,
301                           TextureAxis axis,
302                           float tiles);
303    bool GetSliceTexInfo(SliceType sliceType,
304                         int slice,
305                         TextureAxis axis,
306                         SliceTexInfo& info);
307    void ReportSliceTexInfo(SliceType sliceType,
308                            int slice,
309                            TextureAxis axis,
310                            char *messageBuffer,
311                            unsigned messageBufferSize,
312                            const TexInfoCallback *texInfoCallback);
313    //@}
314    /// @name Subroutines for simple modification
315    //@{
316    void ProcessForAxes(InternalImpl internalImpl,
317                        TextureAxisSelection axes);
318    void Shift(TextureAxis axis,
319               float shift);
320    void Scale(TextureAxis axis,
321               float scale);
322    bool MinAlignInt(TextureAxis axis);
323    bool MaxAlignInt(TextureAxis axis);
324    bool MinMaxAlignAutoScaleInt(TextureAxis axis);
325    bool MinMaxAlignScale(TextureAxis axis,
326                          ScaleOperation op);
327    bool MinMaxAlignStretchInt(TextureAxis axis);
328    bool MinMaxAlignShrinkInt(TextureAxis axis);
329    //@}
330    /// @name Surface measurement
331    //@{
332    float SliceParametricSpeedComponent(PositionAxis axis,
333                                        float t,
334                                        const SlicePatchContext& context);
335    float SliceParametricSpeed(float t,
336                               const SlicePatchContext& context);
337    float EstimateSegmentLength(float startPosition,
338                                float endPosition,
339                                const SlicePatchContext& context);
340    float RefineSegmentLength(float startPosition,
341                              float endPosition,
342                              const SlicePatchContext &context,
343                              float segmentLengthEstimate,
344                              float maxError);
345    //@}
346    /// @name Subroutines for complex modification
347    //@{
348    void GenControlTexFromSurface(TextureAxis axis,
349                                  const Matrix<float>& surfaceValues);
350    void CopyControlTexFromValues(TextureAxis axis,
351                                  const Matrix<float>& values);
352    void GenSurfaceFromControlTex(TextureAxis axis,
353                                  Matrix<float>& surfaceValues);
354    void CopyValuesFromControlTex(TextureAxis axis,
355                                  Matrix<float>& values);
356    void GenScaledDistanceValues(SliceType sliceType,
357                                 int alignSlice,
358                                 const RefSliceDescriptorInt *refSlice,
359                                 bool rawScale,
360                                 float rawScaleOrTiles,
361                                 Matrix<float>& values);
362    void GeneralFunctionInt(const GeneralFunctionFactors& factors,
363                            TextureAxis axis,
364                            int alignRow,
365                            int alignCol,
366                            bool surfaceValues,
367                            const Matrix<float>& rowDistances,
368                            const Matrix<float>& colDistances);
369    //@}
370
371 private: // private static member vars
372
373    static TextureAxis _naturalAxis[NUM_SLICE_TYPES];
374    static bool _radiantScaleInverted[NUM_SLICE_TYPES];
375    static bool _radiantTilesInverted[NUM_SLICE_TYPES];
376    static const char *_infoSliceFormatString[NUM_SLICE_TYPES];
377    static const char *_infoSliceInfscaleFormatString[NUM_SLICE_TYPES];
378    static const char *_warningSliceInfscaleFormatString[NUM_SLICE_TYPES];
379    static const char *_errorBadSliceString[NUM_SLICE_TYPES];
380    static const char *_errorSliceZeroscaleString[NUM_SLICE_TYPES];
381    static const char *_errorSliceZerotilesString[NUM_SLICE_TYPES];
382
383 private: // private member vars
384
385    /**
386     * Handle for the Node object in Radiant that is the patch mesh entity.
387     */
388    scene::Node& _mesh;
389
390    /**
391     * Flag to indicate whether this object was properly generated from the
392     * supplied entity.
393     */
394    bool _valid;
395
396    /**
397     * The control points of the mesh. Modifying the data in this matrix will
398     * modify the mesh entity directly; it is NOT a copy of the entity's data.
399     */
400    PatchControlMatrix _meshData;
401
402    /**
403     * Callback function used to report information about the mesh.
404     */
405    const MessageCallback _infoReportCallback;
406
407    /**
408     * Callback function used to deliver warning messages.
409     */
410    const MessageCallback _warningReportCallback;
411
412    /**
413     * Callback function used to deliver error messages when operations on the
414     * mesh fail.
415     */
416    const MessageCallback _errorReportCallback;
417
418    /**
419     * The number of grid units that would constitute a "natural" scale along
420     * each texture axis, using the mesh's current texture. Radiant's natural
421     * scale is 1/2 as many grid units as there are texture pixels.
422     */
423    float _naturalTexUnits[NUM_TEX_AXES];
424
425    /**
426     * The number of mesh slices of each kind (row or column).
427     */
428    unsigned _numSlices[NUM_SLICE_TYPES];
429
430    /**
431     * Whether the values for a texture axis have been modified since the last
432     * time their min/max/aligned state was calculated.
433     */
434    bool _texMinMaxDirty[NUM_TEX_AXES];
435
436    /**
437     * The minimum values, across the entire mesh, for each texture axis.
438     */
439    float _texMin[NUM_TEX_AXES];
440
441    /**
442     * The maximum values, across the entire mesh, for each texture axis.
443     */
444    float _texMax[NUM_TEX_AXES];
445
446    /**
447     * Whether the minimum value for a texture axis is on a texture boundary.
448     */
449    bool _texMinAligned[NUM_TEX_AXES];
450
451    /**
452     * Whether the maximum value for a texture axis is on a texture boundary.
453     */
454    bool _texMaxAligned[NUM_TEX_AXES];
455
456    /**
457     * The minimum values, across the entire mesh, for each position axis.
458     */
459    float _posMin[NUM_POS_AXES];
460
461    /**
462     * The maximum values, across the entire mesh, for each position axis.
463     */
464    float _posMax[NUM_POS_AXES];
465 };
466
467 #endif // #if !defined(INCLUDED_MESHENTITY_H)