File: TableDefinition.cpp

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (141 lines) | stat: -rw-r--r-- 2,628 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "TableDefinition.h"

#include "parser/DefTokeniser.h"
#include <cmath>

namespace shaders
{

TableDefinition::TableDefinition(const std::string& name) :
    DeclarationBase<ITableDefinition>(decl::Type::Table, name),
	_snap(false),
	_clamp(false)
{}

float TableDefinition::getValue(float index)
{
    ensureParsed();

	// Don't bother if we don't have any values to look up
	if (_values.empty())
	{
		return 0.0f;
	}

    auto numValues = _values.size();

	if (numValues == 1)
	{
		return _values[0];
	}

	if (_clamp)
	{
		if (index > 1.0f) 
		{
			return _values[numValues - 1];
		}
		else if (index < 0.0f) 
		{
			return _values[0];
		}

		// Map the index to the [0..N-1] interval
		index *= numValues - 1;
	}
	else
	{
		// Only take the fractional part of the index
		index = std::fmod(index, 1.0f);

        // Mirror negative indices to the positive range (catch negative -0.0f)
        if (index < 0 && index != 0.0f)
        {
            index += 1.0f;
        }

		// Map the index to the [0..N) interval
		index *= numValues;
	}

    auto leftIdx = static_cast<std::size_t>(std::floor(index)) % numValues;

	if (_snap)
	{
	    // If snap is active, just use the left-bound index
		return _values[leftIdx];
	}

	// No snapping, pick the next value to the right to interpolate
	auto rightIdx = (leftIdx + 1) % numValues;

	float fraction = index - leftIdx;

	return (1-fraction)*_values[leftIdx] + fraction*_values[rightIdx];
}

void TableDefinition::onBeginParsing()
{
    _snap = false;
    _clamp = false;
    _values.clear();
}

void TableDefinition::parseFromTokens(parser::DefTokeniser& tokeniser)
{
	std::size_t level = 0;

	while (tokeniser.hasMoreTokens())
	{
		std::string token = tokeniser.nextToken();

		if (token == "{")
		{
			if (++level > 1)
			{
				throw parser::ParseException("Too many opening braces.");
			}
		}
		else if (token == "}")
		{
			if (level == 0)
			{
				throw parser::ParseException("Too many closing braces.");
			}

			--level;
		}
		else if (token == "clamp")
		{
			if (level != 0)
			{
				throw parser::ParseException("The 'clamp' keyword cannot be used at this scope/position.");
			}

			_clamp = true;
		}
		else if (token == "snap")
		{
			if (level != 0)
			{
				throw parser::ParseException("The 'snap' keyword cannot be used at this scope/position.");
			}

			_snap = true;
		}
		else
		{
			// Expect a numeric value at this point
			try
			{
				_values.push_back(std::stof(token));
			}
			catch (std::invalid_argument& ex)
			{
				throw parser::ParseException("Invalid token '" + token + "' encountered: " + ex.what());
			}
		}
	}
}

} // namespace