Skip to content

Commit 4171d08

Browse files
committed
Add full-colour function-based pigment pattern.
1 parent da27569 commit 4171d08

File tree

7 files changed

+112
-4
lines changed

7 files changed

+112
-4
lines changed

changes.txt

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

52+
- A new special pigment pattern, `user_defined`, has been added to define the
53+
pigment colour directly in terms of a set of functions.
54+
5255
- A new pattern, `potential`, has been added to define a pattern based on the
5356
potential field of a blob or isosurface object.
5457

source/core/material/pattern.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,65 @@ ColourBlendMapConstPtr CubicPattern::GetDefaultBlendMap() const { return gpDefau
400400
unsigned int CubicPattern::NumDiscreteBlendMapEntries() const { return 6; }
401401

402402

403+
ColourFunctionPattern::ColourFunctionPattern()
404+
{
405+
for (int iChannel = 0; iChannel < 5; ++iChannel)
406+
{
407+
pFn[iChannel] = NULL;
408+
}
409+
}
410+
411+
ColourFunctionPattern::ColourFunctionPattern(const ColourFunctionPattern& obj) :
412+
ColourPattern(obj)
413+
{
414+
for (int iChannel = 0; iChannel < 5; ++iChannel)
415+
{
416+
if (obj.pFn[iChannel])
417+
pFn[iChannel] = obj.pFn[iChannel]->Clone();
418+
else
419+
pFn[iChannel] = NULL;
420+
}
421+
}
422+
423+
ColourFunctionPattern::~ColourFunctionPattern()
424+
{
425+
for (int iChannel = 0; iChannel < 5; ++iChannel)
426+
{
427+
if (pFn[iChannel])
428+
delete pFn[iChannel];
429+
}
430+
}
431+
432+
bool ColourFunctionPattern::Evaluate(TransColour& result, const Vector3d& EPoint, const Intersection *pIsection, const Ray *pRay, TraceThreadData *pThread) const
433+
{
434+
for (int iChannel = 0; iChannel < 5; ++iChannel)
435+
{
436+
ColourChannel channelValue = 0.0;
437+
if (pFn[iChannel])
438+
{
439+
GenericFunctionContextPtr pCtx = pFn[iChannel]->AcquireContext(pThread);
440+
pFn[iChannel]->InitArguments(pCtx);
441+
for (int iDimension = 0; iDimension < 3; ++iDimension)
442+
pFn[iChannel]->PushArgument(pCtx, EPoint[iDimension]);
443+
channelValue = pFn[iChannel]->Execute(pCtx);
444+
pFn[iChannel]->ReleaseContext(pCtx);
445+
}
446+
switch (iChannel)
447+
{
448+
case 3: result.filter() = channelValue; break;
449+
case 4: result.transm() = channelValue; break;
450+
default: result.colour()[iChannel] = channelValue; break;
451+
}
452+
}
453+
return true;
454+
}
455+
456+
bool ColourFunctionPattern::HasTransparency() const
457+
{
458+
return (pFn[3] || pFn[4]);
459+
}
460+
461+
403462
bool ColourImagePattern::Evaluate(TransColour& result, const Vector3d& EPoint, const Intersection *pIsection, const Ray *pRay, TraceThreadData *pThread) const
404463
{
405464
// TODO ALPHA - the caller does expect non-premultiplied data, but maybe he could profit from premultiplied data?

source/core/material/pattern.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,22 @@ struct CheckerPattern : public DiscretePattern
455455
virtual unsigned int NumDiscreteBlendMapEntries() const;
456456
};
457457

458+
/// Implements the `user_defined` pattern.
459+
///
460+
/// @todo The additional member variables should possibly be encapsulated.
461+
///
462+
struct ColourFunctionPattern : public ColourPattern
463+
{
464+
GenericScalarFunctionPtr pFn[5];
465+
466+
ColourFunctionPattern();
467+
ColourFunctionPattern(const ColourFunctionPattern& obj);
468+
virtual ~ColourFunctionPattern();
469+
virtual PatternPtr Clone() const { return BasicPattern::Clone(*this); }
470+
virtual bool Evaluate(TransColour& result, const Vector3d& EPoint, const Intersection *pIsection, const Ray *pRay, TraceThreadData *pThread) const;
471+
virtual bool HasTransparency() const;
472+
};
473+
458474
/// Implements the `image_map` pattern.
459475
struct ColourImagePattern : public ColourPattern, public ImagePatternImpl
460476
{

source/parser/parser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8377,6 +8377,16 @@ bool Parser::Parse_Comma (void)
83778377
return true;
83788378
}
83798379

8380+
//******************************************************************************
8381+
8382+
bool Parser::Peek_Token (TOKEN tokenId)
8383+
{
8384+
Get_Token();
8385+
bool tokenMatches = ((Token.Token_Id == tokenId) ||
8386+
(Token.Function_Id == tokenId));
8387+
Unget_Token();
8388+
return tokenMatches;
8389+
}
83808390

83818391

83828392
/*****************************************************************************

source/parser/parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ class Parser : public SceneTask
312312
bool Parse_Begin (bool mandatory = true);
313313
void Parse_End (void);
314314
bool Parse_Comma (void);
315+
bool Peek_Token (TOKEN tokenId);
315316
void Parse_Semi_Colon (bool force_semicolon);
316317
void Destroy_Frame (void);
317318
void MAError (const char *str, long size);
@@ -446,7 +447,7 @@ class Parser : public SceneTask
446447
FUNCTION_PTR Parse_Function(void);
447448
FUNCTION_PTR Parse_FunctionContent(void);
448449
FUNCTION_PTR Parse_FunctionOrContent(void);
449-
void Parse_FunctionOrContentList(GenericScalarFunctionPtr* apFn, unsigned int count);
450+
void Parse_FunctionOrContentList(GenericScalarFunctionPtr* apFn, unsigned int count, bool mandatory = true);
450451
FUNCTION_PTR Parse_DeclareFunction(int *token_id, const char *fn_name, bool is_local);
451452

452453
// parsestr.h/parsestr.cpp

source/parser/parser_functions_utilities.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,18 @@ FUNCTION_PTR Parser::Parse_FunctionOrContent(void)
163163
}
164164

165165

166-
void Parser::Parse_FunctionOrContentList(GenericScalarFunctionPtr* apFn, unsigned int count)
166+
void Parser::Parse_FunctionOrContentList(GenericScalarFunctionPtr* apFn, unsigned int count, bool mandatory)
167167
{
168168
for (unsigned int i = 0; i < count; ++i)
169169
{
170-
if (i > 0)
171-
Parse_Comma();
170+
if (!mandatory && (Peek_Token(RIGHT_CURLY_TOKEN) || Parse_Comma()))
171+
{
172+
apFn[i] = NULL;
173+
continue;
174+
}
172175
apFn[i] = new FunctionVM::CustomFunction(fnVMContext->functionvm, Parse_FunctionOrContent());
176+
if (i < count-1)
177+
Parse_Comma();
173178
}
174179
}
175180

source/parser/parser_materials.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,16 @@ void Parser::Parse_Pattern (PATTERN_T *New, BlendMapTypeId TPat_Type)
10221022
dynamic_cast<FunctionVM*>(sceneData->functionContextFactory), Parse_Function());
10231023
END_CASE
10241024

1025+
CASE (USER_DEFINED_TOKEN)
1026+
if ((TPat_Type != kBlendMapType_Pigment) || (TPat_Type != kBlendMapType_Density))
1027+
Only_In("user_defined", "pigment or density");
1028+
New->Type = COLOUR_PATTERN;
1029+
New->pattern = PatternPtr(new ColourFunctionPattern());
1030+
Parse_Begin();
1031+
Parse_FunctionOrContentList (dynamic_cast<ColourFunctionPattern*>(New->pattern.get())->pFn, 5, false);
1032+
Parse_End();
1033+
END_CASE
1034+
10251035
CASE(PIGMENT_PATTERN_TOKEN)
10261036
Parse_Begin();
10271037
New->Type = GENERIC_PATTERN;
@@ -4798,6 +4808,10 @@ void Parser::Parse_PatternFunction(TPATTERN *New)
47984808
dynamic_cast<FunctionPattern*>(New->pattern.get())->pFn = new FunctionVM::CustomFunction(dynamic_cast<FunctionVM*>(sceneData->functionContextFactory), Parse_Function());
47994809
END_CASE
48004810

4811+
CASE (USER_DEFINED_TOKEN)
4812+
Not_With("user_defined", "function pattern");
4813+
END_CASE
4814+
48014815
CASE(PIGMENT_PATTERN_TOKEN)
48024816
Parse_Begin();
48034817
New->Type = GENERIC_PATTERN;

0 commit comments

Comments
 (0)