Skip to content

Commit 23f936a

Browse files
authored
Implemented potential pattern and isosurface polarity keyword. (#88)
1 parent c52c176 commit 23f936a

File tree

17 files changed

+275
-45
lines changed

17 files changed

+275
-45
lines changed

changes.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ Prior to the release of 3.7.1, the following items still need urgent attention:
4949
New Features
5050
------------
5151

52+
- A new pattern, `potential`, has been added to define a pattern based on the
53+
potential field of a blob or isosurface object.
54+
55+
- A new parameter, `polarity`, has been added to isosurfaces to choose whether
56+
function values above the threshold should indicate the inside or outside.
57+
5258
- Basic support for importing Wavefront OBJ files has been added as an extension
5359
to the `mesh` primitive.
5460

source/base/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#define OFFICIAL_VERSION_STRING "3.7.1"
4646
#define OFFICIAL_VERSION_NUMBER 371
4747

48-
#define POV_RAY_PRERELEASE "x.obj.8787755"
48+
#define POV_RAY_PRERELEASE "x.potential.8787796"
4949

5050
#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
5151
#ifdef POV_RAY_PRERELEASE

source/core/material/pattern.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,9 @@ DBL ContinuousPattern::Evaluate(const Vector3d& EPoint, const Intersection *pIse
301301
{
302302
DBL value = EvaluateRaw(EPoint, pIsection, pRay, pThread);
303303

304+
if (waveType == kWaveType_Raw)
305+
return value;
306+
304307
if(waveFrequency != 0.0)
305308
value = fmod(value * waveFrequency + wavePhase, 1.00001); // TODO FIXME - magic number! Should be 1.0+SOME_EPSILON (or maybe actually 1.0?)
306309

@@ -467,6 +470,29 @@ PigmentPattern::~PigmentPattern()
467470
}
468471

469472

473+
PotentialPattern::PotentialPattern() :
474+
pObject(NULL),
475+
subtractThreshold(false)
476+
{
477+
waveType = kWaveType_Raw;
478+
}
479+
480+
PotentialPattern::PotentialPattern(const PotentialPattern& obj) :
481+
ContinuousPattern(obj),
482+
pObject(NULL),
483+
subtractThreshold(obj.subtractThreshold)
484+
{
485+
if (obj.pObject)
486+
pObject = Copy_Object(obj.pObject);
487+
}
488+
489+
PotentialPattern::~PotentialPattern()
490+
{
491+
if (pObject)
492+
Destroy_Object(pObject);
493+
}
494+
495+
470496
ColourBlendMapConstPtr RadialPattern::GetDefaultBlendMap() const { return gpDefaultBlendMap_Radial; }
471497

472498
ColourBlendMapConstPtr SquarePattern::GetDefaultBlendMap() const { return gpDefaultBlendMap_Square; }
@@ -7802,6 +7828,17 @@ DBL PlanarPattern::EvaluateRaw(const Vector3d& EPoint, const Intersection *pIsec
78027828
}
78037829

78047830

7831+
/*****************************************************************************/
7832+
7833+
DBL PotentialPattern::EvaluateRaw(const Vector3d& EPoint, const Intersection *pIsection, const Ray *pRay, TraceThreadData *pThread) const
7834+
{
7835+
if (pObject != NULL)
7836+
return pObject->GetPotential (EPoint, subtractThreshold, pThread);
7837+
7838+
return 0.0;
7839+
}
7840+
7841+
78057842
/*****************************************************************************
78067843
*
78077844
* FUNCTION

source/core/material/pattern.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ enum PATTERN_IDS
127127

128128
enum WaveType
129129
{
130+
kWaveType_Raw, ///< Use raw pattern value, allowing it to exceed the [0..1] range.
130131
kWaveType_Ramp, ///< Ramps up from 0 to 1, then drops sharply back to 0, and repeats.
131132
kWaveType_Sine, ///< Oscillates between 0 and 1 using a sine-based formula.
132133
kWaveType_Triangle, ///< Ramps up from 0 to 1, then ramps down from 1 to 0, and repeats.
@@ -693,6 +694,22 @@ struct PlanarPattern : public ContinuousPattern
693694
virtual DBL EvaluateRaw(const Vector3d& EPoint, const Intersection *pIsection, const Ray *pRay, TraceThreadData *pThread) const;
694695
};
695696

697+
/// Implements the `potential` pattern.
698+
///
699+
/// @todo The additional member variables should possibly be encapsulated.
700+
///
701+
struct PotentialPattern : public ContinuousPattern
702+
{
703+
ObjectPtr pObject;
704+
bool subtractThreshold;
705+
706+
PotentialPattern();
707+
PotentialPattern(const PotentialPattern& obj);
708+
virtual ~PotentialPattern();
709+
virtual PatternPtr Clone() const { return BasicPattern::Clone(*this); }
710+
virtual DBL EvaluateRaw(const Vector3d& EPoint, const Intersection *pIsection, const Ray *pRay, TraceThreadData *pThread) const;
711+
};
712+
696713
/// Implements the `quilted` pattern.
697714
struct QuiltedPattern : public ContinuousPattern
698715
{

source/core/scene/object.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,10 +826,16 @@ void Destroy_Object(ObjectPtr Object)
826826

827827
ObjectBase::~ObjectBase()
828828
{
829-
Destroy_Transform(Trans);
829+
Destroy_Transform(Trans);
830830
}
831831

832832

833+
double ObjectBase::GetPotential (const Vector3d& p, bool subtractThreshold, TraceThreadData *threaddata) const
834+
{
835+
POV_ASSERT (false);
836+
return 0.0;
837+
}
838+
833839
/*****************************************************************************
834840
*
835841
* FUNCTION

source/core/scene/object.h

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,23 +134,24 @@ namespace pov
134134

135135
/* Object types. */
136136

137-
#define BASIC_OBJECT 0
138-
#define PATCH_OBJECT 1 /* Has no inside, no inverse */
139-
#define TEXTURED_OBJECT 2 /* Has texture, possibly in children */
140-
#define IS_COMPOUND_OBJECT 4 /* Has children field */
141-
#define STURM_OK_OBJECT 8 /* STURM legal */
142-
//#define WATER_LEVEL_OK_OBJECT 16 /* WATER_LEVEL legal */
143-
#define LIGHT_SOURCE_OBJECT 32 /* link me in frame.light_sources */
144-
#define BOUNDING_OBJECT 64 /* This is a holder for bounded object */
145-
//#define SMOOTH_OK_OBJECT 128 /* SMOOTH legal */
146-
#define IS_CHILD_OBJECT 256 /* Object is inside a COMPOUND */
137+
#define BASIC_OBJECT 0x0000u
138+
#define PATCH_OBJECT 0x0001u // Has no inside, no inverse
139+
#define TEXTURED_OBJECT 0x0002u // Has texture, possibly in children
140+
#define IS_COMPOUND_OBJECT 0x0004u // Has children field
141+
#define STURM_OK_OBJECT 0x0008u /* STURM legal */
142+
//#define WATER_LEVEL_OK_OBJECT 0x0010u /* WATER_LEVEL legal */
143+
#define LIGHT_SOURCE_OBJECT 0x0020u /* link me in frame.light_sources */
144+
#define BOUNDING_OBJECT 0x0040u /* This is a holder for bounded object */
145+
//#define SMOOTH_OK_OBJECT 0x0080u /* SMOOTH legal */
146+
#define IS_CHILD_OBJECT 0x0100u /* Object is inside a COMPOUND */
147147
/* NK 1998 - DOUBLE_ILLUMINATE is not used anymore - use DOUBLE_ILLUMINATE_FLAG */
148-
#define HIERARCHY_OK_OBJECT 512 /* NO_HIERARCHY legal */
149-
#define LT_SRC_UNION_OBJECT 1024 /* Union of light_source objects only */
150-
#define LIGHT_GROUP_OBJECT 2048 /* light_group union object [trf] */
151-
#define LIGHT_GROUP_LIGHT_OBJECT 4096 /* light in light_group object [trf] */
152-
#define CSG_DIFFERENCE_OBJECT 8192 /* csg difference object */
153-
#define IS_CSG_OBJECT 16384 /* object is a csg and not some other compound object */
148+
#define HIERARCHY_OK_OBJECT 0x0200u /* NO_HIERARCHY legal */
149+
#define LT_SRC_UNION_OBJECT 0x0400u /* Union of light_source objects only */
150+
#define LIGHT_GROUP_OBJECT 0x0800u /* light_group union object [trf] */
151+
#define LIGHT_GROUP_LIGHT_OBJECT 0x1000u /* light in light_group object [trf] */
152+
#define CSG_DIFFERENCE_OBJECT 0x2000u /* csg difference object */
153+
#define IS_CSG_OBJECT 0x4000u /* object is a csg and not some other compound object */
154+
#define POTENTIAL_OBJECT 0x8000u ///< Object has an intrinsic potential field associated.
154155
#define CHILDREN_FLAGS (PATCH_OBJECT+TEXTURED_OBJECT) /* Reverse inherited flags */
155156

156157

@@ -222,6 +223,7 @@ class ObjectBase
222223
virtual bool Precompute() { return true; };
223224

224225
virtual bool All_Intersections(const Ray&, IStack&, TraceThreadData *) = 0; // could be "const", if it wasn't for isosurface max_gradient estimation stuff
226+
virtual double GetPotential (const Vector3d&, bool subtractThreshold, TraceThreadData *) const;
225227
virtual bool Inside(const Vector3d&, TraceThreadData *) const = 0;
226228
virtual void Normal(Vector3d&, Intersection *, TraceThreadData *) const = 0;
227229
virtual void UVCoord(Vector2d&, const Intersection *, TraceThreadData *) const;

source/core/shape/blob.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,25 @@ bool Blob::Inside(const Vector3d& Test_Point, TraceThreadData *Thread) const
16101610
}
16111611

16121612

1613+
double Blob::GetPotential (const Vector3d& globalPoint, bool subtractThreshold, TraceThreadData *pThread) const
1614+
{
1615+
Vector3d localPoint;
1616+
1617+
if (Trans != NULL)
1618+
MInvTransPoint (localPoint, globalPoint, Trans);
1619+
else
1620+
localPoint = globalPoint;
1621+
1622+
double potential = calculate_field_value (localPoint, pThread);
1623+
if (subtractThreshold)
1624+
potential -= Data->Threshold;
1625+
1626+
if (Test_Flag (this, INVERTED_FLAG))
1627+
return -potential;
1628+
else
1629+
return potential;
1630+
}
1631+
16131632

16141633
/*****************************************************************************
16151634
*

source/core/shape/blob.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ namespace pov
4949
* Global preprocessor defines
5050
******************************************************************************/
5151

52-
#define BLOB_OBJECT (STURM_OK_OBJECT+HIERARCHY_OK_OBJECT)
52+
#define BLOB_OBJECT (STURM_OK_OBJECT+HIERARCHY_OK_OBJECT+POTENTIAL_OBJECT)
5353

5454
// TODO - the following values probably don't have to be all discrete bits, except for BLOB_ENTER_EXIT_FLAG
5555
#define BLOB_ENTER_EXIT_FLAG 1 // internal use only
@@ -136,6 +136,7 @@ class Blob : public ObjectBase
136136

137137
virtual bool All_Intersections(const Ray&, IStack&, TraceThreadData *);
138138
virtual bool Inside(const Vector3d&, TraceThreadData *) const;
139+
virtual double GetPotential (const Vector3d&, bool subtractThreshold, TraceThreadData *) const;
139140
virtual void Normal(Vector3d&, Intersection *, TraceThreadData *) const;
140141
virtual void Translate(const Vector3d&, const TRANSFORM *);
141142
virtual void Rotate(const Vector3d&, const TRANSFORM *);

source/core/shape/isosurface.cpp

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ bool IsoSurface::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThr
128128
if(closed != false)
129129
{
130130
VTmp = Plocal + Depth1 * Dlocal;
131-
tmp = fn.Evaluate(VTmp) - threshold;
131+
tmp = EvaluatePolarized (fn, VTmp);
132132
if(Depth1 > accuracy)
133133
{
134134
if(tmp < 0.0) /* The ray hits the bounding shape */
@@ -149,12 +149,12 @@ bool IsoSurface::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThr
149149
{
150150
Depth1 = accuracy * 5.0;
151151
VTmp = Plocal + Depth1 * Dlocal;
152-
if(fn.Evaluate(VTmp) < threshold)
152+
if (IsInside (fn, VTmp))
153153
Thread->isosurfaceData->Inv3 = -1;
154154
/* Change the sign of the function (IPoint is in the bounding shpae.)*/
155155
}
156156
VTmp = Plocal + Depth2 * Dlocal;
157-
if(fn.Evaluate(VTmp) < threshold)
157+
if (IsInside (fn, VTmp))
158158
{
159159
IPoint = ray.Evaluate(Depth2);
160160
if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
@@ -180,11 +180,11 @@ bool IsoSurface::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThr
180180
{
181181
/* IPoint is on the isosurface */
182182
VTmp = Plocal + tmin * Dlocal;
183-
if(fabs(fn.Evaluate(VTmp) - threshold) < (maxg * accuracy * 4.0))
183+
if (EvaluateAbs (fn, VTmp) < (maxg * accuracy * 4.0))
184184
{
185185
tmin = accuracy * 5.0;
186186
VTmp = Plocal + tmin * Dlocal;
187-
if(fn.Evaluate(VTmp) < threshold)
187+
if (IsInside (fn, VTmp))
188188
Thread->isosurfaceData->Inv3 = -1;
189189
/* change the sign and go into the isosurface */
190190
}
@@ -213,6 +213,8 @@ bool IsoSurface::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThr
213213

214214
if(IFound)
215215
Thread->Stats()[Ray_IsoSurface_Tests_Succeeded]++;
216+
217+
Thread->isosurfaceData->pFn = NULL;
216218
}
217219

218220
if(eval == true)
@@ -264,14 +266,34 @@ bool IsoSurface::Inside(const Vector3d& IPoint, TraceThreadData *Thread) const
264266
if(!container->Inside(New_Point))
265267
return (Test_Flag(this, INVERTED_FLAG));
266268

267-
if(GenericScalarFunctionInstance(Function, Thread).Evaluate(New_Point) > threshold)
269+
GenericScalarFunctionInstance fn(Function, Thread);
270+
if (!IsInside (fn, New_Point))
268271
return (Test_Flag(this, INVERTED_FLAG));
269272

270273
/* Inside the box. */
271274
return (!Test_Flag(this, INVERTED_FLAG));
272275
}
273276

274277

278+
double IsoSurface::GetPotential (const Vector3d& globalPoint, bool subtractThreshold, TraceThreadData *pThread) const
279+
{
280+
Vector3d localPoint;
281+
282+
if (Trans != NULL)
283+
MInvTransPoint (localPoint, globalPoint, Trans);
284+
else
285+
localPoint = globalPoint;
286+
287+
double potential = GenericScalarFunctionInstance(Function, pThread).Evaluate (localPoint);
288+
if (subtractThreshold)
289+
potential -= threshold;
290+
291+
if (Test_Flag (this, INVERTED_FLAG))
292+
return -potential;
293+
else
294+
return potential;
295+
}
296+
275297

276298
/*****************************************************************************
277299
*
@@ -345,6 +367,9 @@ void IsoSurface::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *
345367

346368
Result.normalize();
347369
}
370+
371+
if (positivePolarity)
372+
Result.invert();
348373
}
349374
}
350375

@@ -513,7 +538,9 @@ void IsoSurface::Transform(const TRANSFORM* tr)
513538
*
514539
******************************************************************************/
515540

516-
IsoSurface::IsoSurface() : ObjectBase(ISOSURFACE_OBJECT)
541+
IsoSurface::IsoSurface() :
542+
ObjectBase(ISOSURFACE_OBJECT),
543+
positivePolarity(false)
517544
{
518545
container = shared_ptr<ContainedByShape>(new ContainedByBox());
519546

@@ -588,6 +615,8 @@ ObjectPtr IsoSurface::Copy()
588615
// mark it as copy for use by max_gradient warning code
589616
New->isCopy = true;
590617

618+
New->positivePolarity = positivePolarity;
619+
591620
New->container = shared_ptr<ContainedByShape>(container->Copy());
592621

593622
return (New);
@@ -964,7 +993,31 @@ DBL IsoSurface::Float_Function(ISO_ThreadData& itd, DBL t) const
964993

965994
VTmp = itd.Pglobal + t * itd.Dglobal;
966995

967-
return ((DBL)itd.Inv3 * (itd.pFn->Evaluate(VTmp) - threshold));
996+
return ((DBL)itd.Inv3 * EvaluatePolarized (*itd.pFn, VTmp));
997+
}
998+
999+
1000+
/*****************************************************************************/
1001+
1002+
DBL IsoSurface::EvaluateAbs (GenericScalarFunctionInstance& fn, Vector3d& p) const
1003+
{
1004+
return fabs (threshold - fn.Evaluate (p));
1005+
}
1006+
1007+
DBL IsoSurface::EvaluatePolarized (GenericScalarFunctionInstance& fn, Vector3d& p) const
1008+
{
1009+
if (positivePolarity)
1010+
return threshold - fn.Evaluate (p);
1011+
else
1012+
return fn.Evaluate (p) - threshold;
1013+
}
1014+
1015+
bool IsoSurface::IsInside (GenericScalarFunctionInstance& fn, Vector3d& p) const
1016+
{
1017+
if (positivePolarity)
1018+
return threshold < fn.Evaluate (p);
1019+
else
1020+
return fn.Evaluate (p) < threshold;
9681021
}
9691022

9701023
}

0 commit comments

Comments
 (0)