3 * Declares the MeshEntity class.
4 * @ingroup meshtex-core
8 * Copyright 2012 Joel Baxter
10 * This file is part of MeshTex.
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.
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.
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/>.
26 #if !defined(INCLUDED_MESHENTITY_H)
27 #define INCLUDED_MESHENTITY_H
29 #include "AllocatedMatrix.h"
33 #include "generic/callback.h"
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.
43 * @ingroup meshtex-core
47 public: // public types
50 * Values that represent the texture axes an operation should manipulate.
52 enum TextureAxisSelection
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
60 * Values that represent the kinds of patch mesh slices. Note that the
61 * assigned integer values are significant; do not change.
65 ROW_SLICE_TYPE = 0, ///< row
66 COL_SLICE_TYPE = 1, ///< column
67 NUM_SLICE_TYPES = 2 ///< number of kinds of slice
71 * Type for info/warning/error callbacks. The callback takes a const
72 * char* argument (the message string); it has no return value.
74 typedef Callback1<const char *, void> MessageCallback;
77 * Type for texture scale info callbacks. The callback takes two float
78 * arguments (scale and tiles); it has no return value.
80 typedef Callback2<float, float, void> TexInfoCallback;
83 * Type for defining how to manipulate control point or surface values
84 * according to some linear combination of various values.
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;
96 * Type for choosing a particular slice of a known kind (row or column).
99 bool maxSlice; ///< if true, choose slice with highest index
100 int index; ///< if maxSlice is false, choose slice with this index
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.
109 SliceDesignation designation; ///< the slice
110 bool totalLengthOnly; ///< if true, reference total length only
111 } RefSliceDescriptor;
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.
121 template<typename ObjectClass, void (ObjectClass::*member)(float, float)>
122 class TexInfoCallbackMethod :
123 public BindFirstOpaque2<Member2<ObjectClass, float, float, void, member> >
129 * @param object The object on which to invoke the callback method.
131 TexInfoCallbackMethod(ObjectClass& object) :
132 BindFirstOpaque2<Member2<ObjectClass, float, float, void, member> >(object) {}
135 public: // public methods
139 MeshEntity(scene::Node& mesh,
140 const MessageCallback& infoReportCallback,
141 const MessageCallback& warningReportCallback,
142 const MessageCallback& errorReportCallback);
145 /// @name Interrogation
147 bool IsValid() const;
148 void GetInfo(const int *refRow,
150 const TexInfoCallback *rowTexInfoCallback,
151 const TexInfoCallback *colTexInfoCallback);
153 /// @name Simple modification
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);
161 /// @name Complex modification
163 void SetScale(SliceType sliceType,
164 const SliceDesignation *alignSlice,
165 const RefSliceDescriptor *refSlice,
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,
177 private: // private methods
179 /// @name Unimplemented to prevent copy/assignment
181 MeshEntity(const MeshEntity&);
182 const MeshEntity& operator=(const MeshEntity&);
185 private: // private types
188 * Values that represent the kinds of texture axis.
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
198 * Values that represent the kinds of position (spatial) axis.
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
209 * Values that represent ways of scaling a texture to make it aligned.
213 STRETCH_SCALE_OP, ///< scale by stretching
214 SHRINK_SCALE_OP ///< scale by shrinking
218 * Type for orienting a slice within a particular patch.
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
227 * Type for describing the application of a texture along a given slice,
228 * on a specified texture axis.
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
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.
245 unsigned index; ///< choose slice with this number
246 bool totalLengthOnly; ///< if true, reference total length only
247 } RefSliceDescriptorInt;
250 * Function signature for a private method that applies a preset
251 * transformation on a given texture axis.
253 typedef bool(MeshEntity::*InternalImpl)(TextureAxis axis);
255 private: // private template methods
258 * Utility template function for accessing a matrix element from code that
259 * operates on either kind of slice.
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.
266 * @return The matrix element; can be used as lvalue or rvalue.
268 template<typename Element>
269 inline static Element& MatrixElement(Matrix<Element>& matrix,
273 return (sliceType == ROW_SLICE_TYPE ? matrix(slice, index) :
274 matrix(index, slice));
277 private: // private methods
279 /// @name Internal state refresh
281 void UpdatePosMinMax(PositionAxis axis);
282 void UpdateTexMinMax(TextureAxis axis);
284 /// @name Radiant state management
286 void CreateUndoPoint();
287 void CommitChanges();
289 /// @name Argument resolution
291 int InternalSliceDesignation(const SliceDesignation *sliceDesignation,
292 SliceType sliceType);
293 RefSliceDescriptorInt *InternalRefSliceDescriptor(const RefSliceDescriptor *refSlice,
295 RefSliceDescriptorInt& refSliceInt);
297 /// @name Subroutines for interrogation
299 float GetSliceTexScale(SliceType sliceType,
303 bool GetSliceTexInfo(SliceType sliceType,
307 void ReportSliceTexInfo(SliceType sliceType,
311 unsigned messageBufferSize,
312 const TexInfoCallback *texInfoCallback);
314 /// @name Subroutines for simple modification
316 void ProcessForAxes(InternalImpl internalImpl,
317 TextureAxisSelection axes);
318 void Shift(TextureAxis axis,
320 void Scale(TextureAxis axis,
322 bool MinAlignInt(TextureAxis axis);
323 bool MaxAlignInt(TextureAxis axis);
324 bool MinMaxAlignAutoScaleInt(TextureAxis axis);
325 bool MinMaxAlignScale(TextureAxis axis,
327 bool MinMaxAlignStretchInt(TextureAxis axis);
328 bool MinMaxAlignShrinkInt(TextureAxis axis);
330 /// @name Surface measurement
332 float SliceParametricSpeedComponent(PositionAxis axis,
334 const SlicePatchContext& context);
335 float SliceParametricSpeed(float t,
336 const SlicePatchContext& context);
337 float EstimateSegmentLength(float startPosition,
339 const SlicePatchContext& context);
340 float RefineSegmentLength(float startPosition,
342 const SlicePatchContext &context,
343 float segmentLengthEstimate,
346 /// @name Subroutines for complex modification
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,
358 const RefSliceDescriptorInt *refSlice,
360 float rawScaleOrTiles,
361 Matrix<float>& values);
362 void GeneralFunctionInt(const GeneralFunctionFactors& factors,
367 const Matrix<float>& rowDistances,
368 const Matrix<float>& colDistances);
371 private: // private static member vars
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];
383 private: // private member vars
386 * Handle for the Node object in Radiant that is the patch mesh entity.
391 * Flag to indicate whether this object was properly generated from the
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.
400 PatchControlMatrix _meshData;
403 * Callback function used to report information about the mesh.
405 const MessageCallback _infoReportCallback;
408 * Callback function used to deliver warning messages.
410 const MessageCallback _warningReportCallback;
413 * Callback function used to deliver error messages when operations on the
416 const MessageCallback _errorReportCallback;
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.
423 float _naturalTexUnits[NUM_TEX_AXES];
426 * The number of mesh slices of each kind (row or column).
428 unsigned _numSlices[NUM_SLICE_TYPES];
431 * Whether the values for a texture axis have been modified since the last
432 * time their min/max/aligned state was calculated.
434 bool _texMinMaxDirty[NUM_TEX_AXES];
437 * The minimum values, across the entire mesh, for each texture axis.
439 float _texMin[NUM_TEX_AXES];
442 * The maximum values, across the entire mesh, for each texture axis.
444 float _texMax[NUM_TEX_AXES];
447 * Whether the minimum value for a texture axis is on a texture boundary.
449 bool _texMinAligned[NUM_TEX_AXES];
452 * Whether the maximum value for a texture axis is on a texture boundary.
454 bool _texMaxAligned[NUM_TEX_AXES];
457 * The minimum values, across the entire mesh, for each position axis.
459 float _posMin[NUM_POS_AXES];
462 * The maximum values, across the entire mesh, for each position axis.
464 float _posMax[NUM_POS_AXES];
467 #endif // #if !defined(INCLUDED_MESHENTITY_H)