1 //******************************************************************************
2 ///
3 /// @file core/coretypes.h
4 ///
5 /// Essential types for the render core.
6 ///
7 /// @copyright
8 /// @parblock
9 ///
10 /// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8.
11 /// Copyright 1991-2018 Persistence of Vision Raytracer Pty. Ltd.
12 ///
13 /// POV-Ray is free software: you can redistribute it and/or modify
14 /// it under the terms of the GNU Affero General Public License as
15 /// published by the Free Software Foundation, either version 3 of the
16 /// License, or (at your option) any later version.
17 ///
18 /// POV-Ray is distributed in the hope that it will be useful,
19 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
20 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 /// GNU Affero General Public License for more details.
22 ///
23 /// You should have received a copy of the GNU Affero General Public License
24 /// along with this program.  If not, see <http://www.gnu.org/licenses/>.
25 ///
26 /// ----------------------------------------------------------------------------
27 ///
28 /// POV-Ray is based on the popular DKB raytracer version 2.12.
29 /// DKBTrace was originally written by David K. Buck.
30 /// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
31 ///
32 /// @endparblock
33 ///
34 //******************************************************************************
35 
36 #ifndef POVRAY_CORE_CORETYPES_H
37 #define POVRAY_CORE_CORETYPES_H
38 
39 #include "core/configcore.h"
40 
41 #include <stack>
42 
43 #include "base/colour.h"
44 #include "base/types.h"
45 #include "base/textstream.h"
46 
47 #include "core/math/vector.h"
48 
49 namespace pov
50 {
51 
52 //##############################################################################
53 ///
54 /// @addtogroup PovCore
55 ///
56 /// @{
57 
58 using namespace pov_base;
59 
60 // from <algorithm>; we don't want to always type the namespace for these.
61 using std::min;
62 using std::max;
63 
64 // from <cmath>; we don't want to always type the namespace for these.
65 using std::abs;
66 using std::acos;
67 using std::asin;
68 using std::atan;
69 using std::atan2;
70 using std::ceil;
71 using std::cos;
72 using std::cosh;
73 using std::exp;
74 using std::fabs;
75 using std::floor;
76 using std::fmod;
77 using std::frexp;
78 using std::ldexp;
79 using std::log;
80 using std::log10;
81 using std::modf;
82 using std::pow;
83 using std::sin;
84 using std::sinh;
85 using std::sqrt;
86 using std::tan;
87 using std::tanh;
88 
89 // Simple Scalar Square
90 template<typename T>
Sqr(T a)91 inline T Sqr(T a)
92 {
93     return a * a;
94 }
95 
96 class ObjectBase;
97 typedef ObjectBase * ObjectPtr;
98 typedef const ObjectBase * ConstObjectPtr;
99 
100 typedef struct Transform_Struct TRANSFORM;
101 
102 /// @}
103 ///
104 //##############################################################################
105 ///
106 /// @addtogroup PovCoreMaterialPattern
107 ///
108 /// @{
109 
110 typedef struct Pattern_Struct TPATTERN;
111 typedef struct Texture_Struct TEXTURE;
112 typedef struct Pigment_Struct PIGMENT;
113 typedef struct Tnormal_Struct TNORMAL;
114 typedef struct Finish_Struct FINISH;
115 
116 typedef TEXTURE* TexturePtr;
117 
118 /// @}
119 ///
120 //##############################################################################
121 ///
122 /// @addtogroup PovCoreMaterialMedia
123 ///
124 /// @{
125 
126 class Media
127 {
128     public:
129         int Type;
130         int Intervals;
131         int Min_Samples;
132         int Max_Samples;
133         unsigned Sample_Method : 8;
134         bool is_constant : 1;
135         bool use_absorption : 1;
136         bool use_emission : 1;
137         bool use_extinction : 1;
138         bool use_scattering : 1;
139         bool ignore_photons : 1;
140         DBL Jitter;
141         DBL Eccentricity;
142         DBL sc_ext;
143         MathColour Absorption;
144         MathColour Emission;
145         MathColour Extinction;
146         MathColour Scattering;
147 
148         DBL Ratio;
149         DBL Confidence;
150         DBL Variance;
151         DBL *Sample_Threshold;
152 
153         DBL AA_Threshold;
154         int AA_Level;
155 
156         vector<PIGMENT*> Density;
157 
158         Media();
159         Media(const Media&);
160         ~Media();
161 
162         Media& operator=(const Media&);
163 
164         void Transform(const TRANSFORM *trans);
165 
166         void PostProcess();
167 };
168 
169 /// @}
170 ///
171 //##############################################################################
172 ///
173 /// @addtogroup PovCoreMaterialInterior
174 ///
175 /// @{
176 
177 class SubsurfaceInterior;
178 class Interior
179 {
180     public:
181         int  hollow, Disp_NElems;
182         SNGL IOR, Dispersion;
183         SNGL Caustics, Old_Refract;
184         SNGL Fade_Distance, Fade_Power;
185         MathColour Fade_Colour;
186         vector<Media> media;
187         shared_ptr<SubsurfaceInterior> subsurface;
188 
189         Interior();
190         Interior(const Interior&);
191         ~Interior();
192 
193         void Transform(const TRANSFORM *trans);
194 
195         void PostProcess();
196     private:
197         Interior& operator=(const Interior&);
198 };
199 
200 typedef shared_ptr<Interior> InteriorPtr;
201 typedef shared_ptr<const Interior> ConstInteriorPtr;
202 
203 /// @}
204 ///
205 //##############################################################################
206 ///
207 /// @addtogroup PovCoreMaterialPattern
208 ///
209 /// @{
210 
211 struct BasicPattern;
212 
213 typedef shared_ptr<BasicPattern> PatternPtr;
214 typedef shared_ptr<const BasicPattern> ConstPatternPtr;
215 
216 
217 struct Pattern_Struct
218 {
219     unsigned short Type;
220     unsigned short Flags;
221     PatternPtr pattern;
222 };
223 
224 /// @}
225 ///
226 //##############################################################################
227 ///
228 /// @addtogroup PovCore
229 ///
230 /// @{
231 
232 typedef struct Material_Struct MATERIAL;
233 
234 struct Material_Struct
235 {
236     TEXTURE *Texture;
237     TEXTURE *Interior_Texture;
238     InteriorPtr interior;
239 };
240 
241 class LightSource;
242 
243 template<typename T>
244 class RefPool
245 {
246     public:
RefPool()247         RefPool() { }
~RefPool()248         ~RefPool() { for(typename vector<T*>::iterator i(pool.begin()); i != pool.end(); i++) delete *i; pool.clear(); }
249 
alloc()250         T *alloc() { if(pool.empty()) return new T(); T *ptr(pool.back()); pool.pop_back(); return ptr; }
release(T * ptr)251         void release(T *ptr) { pool.push_back(ptr); }
252     private:
253         vector<T*> pool;
254 
255         RefPool(const RefPool&);
256         RefPool& operator=(RefPool&);
257 };
258 
259 template<typename T>
260 struct RefClearDefault
261 {
operatorRefClearDefault262     void operator()(T&) { }
263 };
264 
265 template<typename T>
266 struct RefClearContainer
267 {
operatorRefClearContainer268     void operator()(T& p) { p.clear(); }
269 };
270 
271 template<typename T, class C = RefClearDefault<T> >
272 class Ref
273 {
274     public:
Ref(RefPool<T> & p)275         Ref(RefPool<T>& p) : pool(p), ptr(p.alloc()) { }
~Ref()276         ~Ref() { C c; c(*ptr); pool.release(ptr); }
277 
278         T& operator*() { return *ptr; }
279         const T& operator*() const { return *ptr; }
280 
281         T *operator->() { return ptr; }
282         const T *operator->() const { return ptr; }
283     private:
284         RefPool<T>& pool;
285         T *ptr;
286 
287         Ref();
288         Ref(const Ref&);
289         Ref& operator=(Ref&);
290 };
291 
292 class ObjectDebugHelper
293 {
294     public:
295         int Index;
296         bool IsCopy;
297         std::string Tag;
298 
ObjectDebugHelper()299         ObjectDebugHelper() { Index = ObjectIndex++; IsCopy = false; }
300         ObjectDebugHelper& operator=(const ObjectDebugHelper& src) { Index = ObjectIndex++; IsCopy = true; Tag = src.Tag; return *this; }
301 
302         std::string& SimpleDesc (std::string& result);
303     private:
304         static int ObjectIndex;
ObjectDebugHelper(const ObjectDebugHelper & src)305         ObjectDebugHelper(const ObjectDebugHelper& src) { Index = ObjectIndex++; IsCopy = true; Tag = src.Tag; }
306 };
307 
308 typedef unsigned short HF_VAL;
309 
310 /// @}
311 ///
312 //##############################################################################
313 ///
314 /// @addtogroup PovCoreRender
315 ///
316 /// @{
317 
318 /// Ray-object intersection data.
319 ///
320 /// This class holds various information on a ray-object intersection.
321 ///
322 class Intersection
323 {
324     public:
325 
326         /// Distance from the intersecting ray's origin.
327         DBL Depth;
328         /// Point of the intersection in global coordinate space.
329         Vector3d IPoint;
330         /// Unperturbed surface normal at the intersection point.
331         /// @attention This is not necessarily the true geometric surface normal, as it may include fake smoothing.
332         /// @note This value is invalid if haveNormal is false.
333         /// @todo We should have two distinct vectors: A true geometric one, and a separate one for faked smoothing.
334         Vector3d INormal;
335         /// Perturbed normal vector (set during texture evaluation).
336         Vector3d PNormal;
337         /// UV texture coordinate.
338         Vector2d Iuv;
339         /// Intersected object.
340         ObjectPtr Object;
341         /// Root-level parent CSG object for cutaway textures.
342         ObjectPtr Csg;
343 
344         /// @name Object-Specific Auxiliary Data
345         /// These members hold information specific to particular object types, typically generated during
346         /// intersection testing, to be re-used later for normal and/or UV coordinate computation.
347         /// @note These values may be invalid or meaningless depending on the type of object intersected.
348         /// @{
349 
350         /// Point of the intersection in local coordinate space (used by Blob and SpindleTorus)
351         /// @note This value is invalid in Blob if haveLocalIPoint is false.
352         Vector3d LocalIPoint;
353         /// Generic auxiliary float data #1 (used by Prism, Lathe)
354         DBL d1;
355         /// Generic auxiliary pointer data (used by Mesh)
356         const void *Pointer;
357         /// Generic auxiliary integer data #1 (used by Sor, Prism, Isosurface, Lathe, Cones, Boxes)
358         int i1;
359         /// Generic auxiliary integer data #2 (used by Sor, Prism, Isosurface)
360         int i2;
361         /// Flag to indicate whether INormal was computed during intersection testing (used by HField)
362         /// @note Objects either always or never computing INormal during intersection testing don't use this flag.
363         bool haveNormal : 1;
364         /// Flag to indicate whether LocalIPoint has already been computed.
365         bool haveLocalIPoint : 1;
366         /// Generic auxiliary boolean data #1 (used by SpindleTorus)
367         bool b1 : 1;
368 
369         /// @}
370 
Intersection()371         Intersection() :
372             Depth(BOUND_HUGE), Object(nullptr), Csg(nullptr),
373             d1(0.0), Pointer(nullptr), i1(0), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
374         {}
375 
Intersection(DBL d,const Vector3d & v,ObjectPtr o)376         Intersection(DBL d, const Vector3d& v, ObjectPtr o) :
377             Depth(d), IPoint(v), Iuv(v), Object(o), Csg(nullptr),
378             d1(0.0), Pointer(nullptr), i1(0), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
379         {}
380 
Intersection(DBL d,const Vector3d & v,const Vector3d & n,ObjectPtr o)381         Intersection(DBL d, const Vector3d& v, const Vector3d& n, ObjectPtr o) :
382             Depth(d), IPoint(v), INormal(n), Iuv(v), Object(o), Csg(nullptr),
383             d1(0.0), Pointer(nullptr), i1(0), i2(0), haveNormal(true), haveLocalIPoint(false), b1(false)
384         {}
385 
Intersection(DBL d,const Vector3d & v,const Vector2d & uv,ObjectPtr o)386         Intersection(DBL d, const Vector3d& v, const Vector2d& uv, ObjectPtr o) :
387             Depth(d), IPoint(v), Iuv(uv), Object(o), Csg(nullptr),
388             d1(0.0), Pointer(nullptr), i1(0), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
389         {}
390 
Intersection(DBL d,const Vector3d & v,const Vector3d & n,const Vector2d & uv,ObjectPtr o)391         Intersection(DBL d, const Vector3d& v, const Vector3d& n, const Vector2d& uv, ObjectPtr o) :
392             Depth(d), IPoint(v), INormal(n), Iuv(uv), Object(o), Csg(nullptr),
393             d1(0.0), Pointer(nullptr), i1(0), i2(0), haveNormal(true), haveLocalIPoint(false), b1(false)
394         {}
395 
Intersection(DBL d,const Vector3d & v,ObjectPtr o,const void * a)396         Intersection(DBL d, const Vector3d& v, ObjectPtr o, const void *a) :
397             Depth(d), IPoint(v), Iuv(v), Object(o), Csg(nullptr),
398             d1(0.0), Pointer(a), i1(0), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
399         {}
400 
Intersection(DBL d,const Vector3d & v,const Vector2d & uv,ObjectPtr o,const void * a)401         Intersection(DBL d, const Vector3d& v, const Vector2d& uv, ObjectPtr o, const void *a) :
402             Depth(d), IPoint(v), Iuv(uv), Object(o), Csg(nullptr),
403             d1(0.0), Pointer(a), i1(0), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
404         {}
405 
406         /// @todo Why does this not set Iuv=IPoint, as other constructors do?
Intersection(DBL d,const Vector3d & v,ObjectPtr o,int a)407         Intersection(DBL d, const Vector3d& v, ObjectPtr o, int a) :
408             Depth(d), IPoint(v), Object(o), Csg(nullptr),
409             d1(0.0), Pointer(nullptr), i1(a), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
410         {}
411 
412         /// @todo Why does this not set Iuv=IPoint, as other constructors do?
Intersection(DBL d,const Vector3d & v,ObjectPtr o,DBL a)413         Intersection(DBL d, const Vector3d& v, ObjectPtr o, DBL a) :
414             Depth(d), IPoint(v), Object(o), Csg(nullptr),
415             d1(a), Pointer(nullptr), i1(0), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
416         {}
417 
418         /// @todo Why does this not set Iuv=IPoint, as other constructors do?
Intersection(DBL d,const Vector3d & v,ObjectPtr o,int a,int b)419         Intersection(DBL d, const Vector3d& v, ObjectPtr o, int a, int b) :
420             Depth(d), IPoint(v), Object(o), Csg(nullptr),
421             d1(0.0), Pointer(nullptr), i1(a), i2(b), haveNormal(false), haveLocalIPoint(false), b1(false)
422         {}
423 
424         /// @todo Why does this not set Iuv=IPoint, as other constructors do?
Intersection(DBL d,const Vector3d & v,ObjectPtr o,int a,DBL b)425         Intersection(DBL d, const Vector3d& v, ObjectPtr o, int a, DBL b) :
426             Depth(d), IPoint(v), Object(o), Csg(nullptr),
427             d1(b), Pointer(nullptr), i1(a), i2(0), haveNormal(false), haveLocalIPoint(false), b1(false)
428         {}
429 
430         /// @todo Why does this not set Iuv=IPoint, as other constructors do?
Intersection(DBL d,const Vector3d & v,ObjectPtr o,int a,int b,DBL c)431         Intersection(DBL d, const Vector3d& v, ObjectPtr o, int a, int b, DBL c) :
432             Depth(d), IPoint(v), Object(o), Csg(nullptr),
433             d1(c), Pointer(nullptr), i1(a), i2(b), haveNormal(false), haveLocalIPoint(false), b1(false)
434         {}
435 
436         /// @todo Why does this not set Iuv=IPoint, as other constructors do?
Intersection(DBL d,const Vector3d & v,ObjectPtr o,const Vector3d & lv,bool a)437         Intersection(DBL d, const Vector3d& v, ObjectPtr o, const Vector3d& lv, bool a) :
438             Depth(d), IPoint(v), Object(o), Csg(nullptr),
439             LocalIPoint(lv), d1(0.0), Pointer(nullptr), i1(0), i2(0), haveNormal(false), haveLocalIPoint(true), b1(a)
440         {}
441 
~Intersection()442         ~Intersection() { }
443 };
444 
445 typedef std::stack<Intersection, vector<Intersection> > IStackData;
446 typedef RefPool<IStackData> IStackPool;
447 typedef Ref<IStackData> IStack;
448 
449 struct BasicRay
450 {
451     Vector3d Origin;
452     Vector3d Direction;
453 
BasicRayBasicRay454     inline BasicRay() {}
BasicRayBasicRay455     inline BasicRay(const BasicRay& obj) : Origin(obj.Origin), Direction(obj.Direction) {}
BasicRayBasicRay456     inline BasicRay(const Vector3d& ov, const Vector3d& dv) : Origin(ov), Direction(dv) {}
EvaluateBasicRay457     inline Vector3d Evaluate(double depth) const { return Origin + Direction * depth; }
458 
459     /// Make sure the ray's direction is normalized.
460     /// @return     The length of the direction vector before normalization.
NormalizeBasicRay461     inline DBL Normalize() { DBL len = Direction.length(); Direction /= len; return len; }
462 
GetOriginBasicRay463     inline const Vector3d& GetOrigin() const { return Origin; }
GetDirectionBasicRay464     inline const Vector3d& GetDirection() const { return Direction; }
465 
GetOriginBasicRay466     inline Vector3d& GetOrigin() { return Origin; }
GetDirectionBasicRay467     inline Vector3d& GetDirection() { return Direction; }
468 };
469 
470 struct TraceTicket;
471 
472 class Ray;
473 
474 struct RayObjectCondition
475 {
476     virtual bool operator()(const Ray& ray, ConstObjectPtr object, DBL data) const = 0;
477 };
478 
479 struct TrueRayObjectCondition : public RayObjectCondition
480 {
operatorTrueRayObjectCondition481     virtual bool operator()(const Ray&, ConstObjectPtr, DBL) const { return true; }
482 };
483 
484 struct PointObjectCondition
485 {
486     virtual bool operator()(const Vector3d& point, ConstObjectPtr object) const = 0;
487 };
488 
489 struct TruePointObjectCondition : public PointObjectCondition
490 {
operatorTruePointObjectCondition491     virtual bool operator()(const Vector3d&, ConstObjectPtr) const { return true; }
492 };
493 
494 /// @}
495 ///
496 //##############################################################################
497 ///
498 /// @addtogroup PovCore
499 ///
500 /// @{
501 
502 struct FrameSettings
503 {
504     DBL Clock_Value;      // May change between frames of an animation
505     int FrameNumber;      // May change between frames of an animation
506 
507     int InitialFrame;
508     DBL InitialClock;
509 
510     int FinalFrame;
511     int FrameNumWidth;
512     DBL FinalClock;
513 
514     int SubsetStartFrame;
515     DBL SubsetStartPercent;
516     int SubsetEndFrame;
517     DBL SubsetEndPercent;
518 
519     bool Field_Render_Flag;
520     bool Odd_Field_Flag;
521 };
522 
523 /// @}
524 ///
525 //##############################################################################
526 ///
527 /// @addtogroup PovCoreMaterialPattern
528 ///
529 /// @{
530 
531 class Fractal;
532 
533 class FractalRules
534 {
535     public:
~FractalRules()536         virtual ~FractalRules() {}
537         virtual void CalcNormal (Vector3d&, int, const Fractal *, DBL **) const = 0;
538         virtual bool Iterate (const Vector3d&, const Fractal *, DBL **) const = 0;
539         virtual bool Iterate (const Vector3d&, const Fractal *, const Vector3d&, DBL *, DBL **) const = 0;
540         virtual bool Bound (const BasicRay&, const Fractal *, DBL *, DBL *) const = 0;
541 };
542 
543 typedef shared_ptr<FractalRules> FractalRulesPtr;
544 
545 struct QualityFlags
546 {
547     bool ambientOnly    : 1;
548     bool quickColour    : 1;
549     bool shadows        : 1;
550     bool areaLights     : 1;
551     bool refractions    : 1;
552     bool reflections    : 1;
553     bool normals        : 1;
554     bool media          : 1;
555     bool radiosity      : 1;
556     bool photons        : 1;
557     bool subsurface     : 1;
558 
QualityFlagsQualityFlags559     explicit QualityFlags(int level) :
560         ambientOnly (level <= 1),
561         quickColour (level <= 5),
562         shadows     (level >= 4),
563         areaLights  (level >= 5),
564         refractions (level >= 6),
565         reflections (level >= 8),
566         normals     (level >= 8),
567         media       (level >= 9),
568         radiosity   (level >= 9),
569         photons     (level >= 9),
570         subsurface  (level >= 9)
571     {}
572 };
573 
574 /// @}
575 ///
576 //##############################################################################
577 ///
578 /// @defgroup PovCoreFunction User-Defined Functions
579 /// @ingroup PovCore
580 ///
581 /// @{
582 
583 class TraceThreadData;
584 
585 class GenericFunctionContext
586 {
587     public:
~GenericFunctionContext()588         virtual ~GenericFunctionContext() {}
589 };
590 
591 typedef GenericFunctionContext* GenericFunctionContextPtr;
592 
593 class GenericFunctionContextFactory
594 {
595     public:
GenericFunctionContextFactory()596         GenericFunctionContextFactory() : mRefCounter(0) {}
~GenericFunctionContextFactory()597         virtual ~GenericFunctionContextFactory() {}
598         virtual GenericFunctionContextPtr CreateFunctionContext(TraceThreadData* pTd) = 0;
599 
600     private:
601         mutable size_t mRefCounter;
602         friend void intrusive_ptr_add_ref(GenericFunctionContextFactory* f);
603         friend void intrusive_ptr_release(GenericFunctionContextFactory* f);
604 };
605 
intrusive_ptr_add_ref(GenericFunctionContextFactory * f)606 inline void intrusive_ptr_add_ref(GenericFunctionContextFactory* f) { ++f->mRefCounter; }
intrusive_ptr_release(GenericFunctionContextFactory * f)607 inline void intrusive_ptr_release(GenericFunctionContextFactory* f) { if (!(--f->mRefCounter)) delete f; }
608 
609 typedef intrusive_ptr<GenericFunctionContextFactory>    GenericFunctionContextFactoryIPtr;
610 typedef GenericFunctionContextFactory*                  GenericFunctionContextFactoryTPtr;
611 
612 struct SourceInfo
613 {
614     char*                           name;
615     UCS2*                           filename;
616     pov_base::ITextStream::FilePos  filepos;
617     int                             col;
618 };
619 
620 template<typename RETURN_T, typename ARG_T>
621 class GenericCustomFunction
622 {
623 public:
~GenericCustomFunction()624     virtual ~GenericCustomFunction() {}
625     virtual GenericFunctionContextPtr AcquireContext(TraceThreadData* pThreadData) = 0;
626     virtual void ReleaseContext(GenericFunctionContextPtr pContext) = 0;
627     virtual void InitArguments(GenericFunctionContextPtr pContext) = 0;
628     virtual void PushArgument(GenericFunctionContextPtr pContext, ARG_T arg) = 0;
629     virtual RETURN_T Execute(GenericFunctionContextPtr pContext) = 0;
630     virtual GenericCustomFunction* Clone() const = 0;
GetSourceInfo()631     virtual const SourceInfo* GetSourceInfo() const { return nullptr; }
632 };
633 
634 typedef GenericCustomFunction<double, double> GenericScalarFunction;
635 typedef GenericScalarFunction* GenericScalarFunctionPtr;
636 
637 template<typename RETURN_T, typename ARG_T>
638 class GenericCustomFunctionInstance
639 {
640 public:
GenericCustomFunctionInstance(GenericCustomFunction<RETURN_T,ARG_T> * pFn,TraceThreadData * pThreadData)641     inline GenericCustomFunctionInstance(GenericCustomFunction<RETURN_T,ARG_T>* pFn, TraceThreadData* pThreadData) :
642         mpFunction(pFn), mpContext(pFn->AcquireContext(pThreadData)), mReInit(true)
643     {
644         POV_ASSERT(mpFunction != nullptr);
645         POV_ASSERT(mpContext  != nullptr);
646     }
647 
~GenericCustomFunctionInstance()648     inline ~GenericCustomFunctionInstance()
649     {
650         mpFunction->ReleaseContext(mpContext);
651     }
652 
PushArgument(ARG_T arg)653     inline void PushArgument(ARG_T arg)
654     {
655         if (mReInit)
656         {
657             mpFunction->InitArguments(mpContext);
658             mReInit = false;
659         }
660         mpFunction->PushArgument(mpContext, arg);
661     }
662 
Evaluate()663     inline RETURN_T Evaluate()
664     {
665         RETURN_T result = mpFunction->Execute(mpContext);
666         mReInit = true;
667         return result;
668     }
669 
670     template<typename T1>
Evaluate(T1 arg1)671     inline RETURN_T Evaluate(T1 arg1)
672     {
673         PushArgument(arg1);
674         return Evaluate();
675     }
676 
677     template<typename T1, typename T2>
Evaluate(T1 arg1,T2 arg2)678     inline RETURN_T Evaluate(T1 arg1, T2 arg2)
679     {
680         PushArgument(arg1);
681         PushArgument(arg2);
682         return Evaluate();
683     }
684 
685     template<typename T1, typename T2, typename T3>
Evaluate(T1 arg1,T2 arg2,T3 arg3)686     inline RETURN_T Evaluate(T1 arg1, T2 arg2, T3 arg3)
687     {
688         PushArgument(arg1);
689         PushArgument(arg2);
690         PushArgument(arg3);
691         return Evaluate();
692     }
693 
Evaluate(const Vector2d & argV)694     inline RETURN_T Evaluate(const Vector2d& argV)
695     {
696         return Evaluate(argV.u(), argV.v());
697     }
698 
Evaluate(const Vector3d & argV)699     inline RETURN_T Evaluate(const Vector3d& argV)
700     {
701         return Evaluate(argV.x(), argV.y(), argV.z());
702     }
703 
704 protected:
705     GenericCustomFunction<RETURN_T,ARG_T>*  mpFunction;
706     GenericFunctionContextPtr               mpContext;
707     bool                                    mReInit;
708 
709 private:
710     GenericCustomFunctionInstance();
711 };
712 
713 typedef GenericCustomFunctionInstance<double, double> GenericScalarFunctionInstance;
714 typedef GenericScalarFunctionInstance* GenericScalarFunctionInstancePtr;
715 
716 /// @}
717 ///
718 //##############################################################################
719 
720 }
721 
722 #endif // POVRAY_CORE_CORETYPES_H
723