@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
223 lines (208 loc) • 5.79 kB
text/typescript
import {CubicInterpolant} from 'three';
import {MathUtils} from 'three';
import {arraySortBy} from '../../../core/ArrayUtils';
export interface RampPointJson {
position: number;
value: number;
}
export interface RampValueJson {
points: RampPointJson[];
interpolation: RampInterpolation;
}
export class RampPoint {
constructor(private _position: number = 0, private _value: number = 0) {}
toJSON(): RampPointJson {
return {
position: this._position,
value: this._value,
};
}
position() {
return this._position;
}
value() {
return this._value;
}
copy(point: RampPoint) {
this._position = point.position();
this._value = point.value();
}
clone() {
const point = new RampPoint();
point.copy(this);
return point;
}
isEqual(other_point: RampPoint) {
return this._position == other_point.position() && this._value == other_point.value();
}
isEqualJSON(json: RampPointJson) {
return this._position == json.position && this._value == json.value;
}
fromJSON(json: RampPointJson) {
this._position = json.position;
this._value = json.value;
}
static areEqualJSON(json1: RampPointJson, json2: RampPointJson) {
return json1.position == json2.position && json1.value == json2.value;
}
static fromJSON(json: RampPointJson) {
return new RampPoint(json.position, json.value);
}
}
export enum RampInterpolation {
CUBIC = 'cubic',
}
export const RAMP_INTERPOLATIONS: RampInterpolation[] = [RampInterpolation.CUBIC];
export class RampValue {
private _uuid: string;
constructor(
private _interpolation: RampInterpolation = RampInterpolation.CUBIC,
private _points: RampPoint[] = []
) {
this._uuid = MathUtils.generateUUID();
}
uuid() {
return this._uuid;
}
interpolation() {
return this._interpolation;
}
points() {
return this._points;
}
static createInterpolantFromValues(positions: Float32Array, values: Float32Array) {
const valuesCount = 1;
const interpolatedValues = new Float32Array(valuesCount);
return new CubicInterpolant(positions, values, valuesCount, interpolatedValues);
}
createInterpolant() {
return RampValue.createInterpolant(this);
}
static createInterpolant(rampValue: RampValue) {
const points = rampValue.points();
const sortedPoints = arraySortBy(points, (point) => point.position());
const positions = new Float32Array(sortedPoints.length);
const values = new Float32Array(sortedPoints.length);
let i = 0;
for (const sortedPoint of sortedPoints) {
positions[i] = sortedPoint.position();
values[i] = sortedPoint.value();
i++;
}
return this.createInterpolantFromValues(positions, values);
}
static fromJSON(json: RampValueJson): RampValue {
const points = [];
for (const jsonPoint of json.points) {
points.push(RampPoint.fromJSON(jsonPoint));
}
let interpolation = json.interpolation;
if (interpolation == null || (interpolation as string) == '') {
interpolation = RampInterpolation.CUBIC;
}
return new RampValue(interpolation, points);
}
toJSON(): RampValueJson {
return {
interpolation: this._interpolation,
points: this._points.map((p) => p.toJSON()),
};
}
clone(): RampValue {
const ramp = new RampValue();
ramp.copy(this);
return ramp;
}
copy(ramp: RampValue) {
this._interpolation = ramp.interpolation();
const newPointsCount = ramp.points().length;
const currentPointsCount = this._points.length;
if (currentPointsCount > newPointsCount) {
const pointsCountToRemove = currentPointsCount - newPointsCount;
const spliceStart = currentPointsCount - pointsCountToRemove;
this._points.splice(spliceStart, pointsCountToRemove);
}
let index = 0;
for (const point of ramp.points()) {
const currentPoint = this._points[index];
if (currentPoint) {
currentPoint.copy(point);
} else {
this._points.push(point.clone());
}
index += 1;
}
}
isEqual(other_ramp_value: RampValue): boolean {
if (this._interpolation != other_ramp_value.interpolation()) {
return false;
}
const other_points = other_ramp_value.points();
if (this._points.length != other_points.length) {
return false;
}
let index = 0;
for (const point of this._points) {
const other_point = other_points[index];
if (!point.isEqual(other_point)) {
return false;
}
index += 1;
}
return true;
}
isEqualJSON(json: RampValueJson) {
if (this._interpolation != json.interpolation) {
return false;
}
if (this._points.length != json.points.length) {
return false;
}
let index = 0;
for (const point of this._points) {
const other_point = json.points[index];
if (!point.isEqualJSON(other_point)) {
return false;
}
index += 1;
}
return true;
}
static are_json_equal(json1: RampValueJson, json2: RampValueJson) {
if (json1.interpolation != json2.interpolation) {
return false;
}
if (json1.points.length != json2.points.length) {
return false;
}
let index = 0;
for (const point1 of json1.points) {
const point2 = json2.points[index];
if (!RampPoint.areEqualJSON(point1, point2)) {
return false;
}
index += 1;
}
return true;
}
fromJSON(json: RampValueJson) {
this._interpolation = json.interpolation;
const newPointsCount = json.points.length;
const currentPointsCount = this._points.length;
if (currentPointsCount > newPointsCount) {
const pointsCountToRemove = currentPointsCount - newPointsCount;
const spliceStart = currentPointsCount - pointsCountToRemove;
this._points.splice(spliceStart, pointsCountToRemove);
}
let index = 0;
for (const json_point of json.points) {
const currentPoint = this._points[index];
if (currentPoint) {
currentPoint.fromJSON(json_point);
} else {
this._points.push(RampPoint.fromJSON(json_point));
}
index += 1;
}
}
}