@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
236 lines (197 loc) • 6.64 kB
JavaScript
import { Color } from "../../../../../core/color/Color.js";
import { TubeMaterialType } from "./TubeMaterialType.js";
import { assert } from "../../../../../core/assert.js";
import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
import { CapType } from "./CapType.js";
import { StandardMaterialDefinition } from "./StandardMaterialDefinition.js";
import { BasicMaterialDefinition } from "./BasicMaterialDefinition.js";
import { PathNormalType } from "./PathNormalType.js";
import Vector3 from "../../../../../core/geom/Vector3.js";
const DEFAULT_COLOR = Object.freeze({ r: 1, g: 1, b: 1 });
export class TubePathStyle {
constructor() {
/**
*
* @type {Color}
*/
this.color = new Color(1, 1, 1);
/**
* @type {TubeMaterialType}
*/
this.material_type = TubeMaterialType.Unknown;
/**
*
* @type {StandardMaterialDefinition|MatcapMaterialDefinition|BasicMaterialDefinition|null}
*/
this.material = null;
/**
*
* @type {number}
*/
this.opacity = 1;
/**
*
* @type {number}
*/
this.width = 1;
/**
*
* @type {number[]}
*/
this.shape = build_circle_shape(16);
/**
*
* @type {number[]|Float32Array|null}
*/
this.shape_normals = null;
/**
*
* @type {number}
*/
this.resolution = 10;
/**
*
* @type {boolean}
*/
this.cast_shadow = false;
/**
*
* @type {boolean}
*/
this.receive_shadow = false;
/**
* @type {PathNormalType}
*/
this.path_normal_type = PathNormalType.Automatic;
/**
*
* @type {Vector3}
*/
this.path_normal = Vector3.up;
/**
* Which parts of the path to visualise, in normalized offsets
* @example [ 0, 1 ] = whole path
* @example [ 0, 0.5 ] = first half of the path
* @example [ 0.5, 0.6 ] = segment from 50% along the path, to 60% along the path
* @example [ 0, 0.1, 0.9, 1] = first 10% of the path, and last 10% of the path
* @type {number[]}
*/
this.path_mask = [0, 1];
/**
* @type {CapType}
*/
this.cap_type = CapType.Flat;
}
/**
* @deprecated
* @param {number} v
*/
set radial_resolution(v) {
console.warn(".radial_resolution property is deprecated, use .shape directly instead");
this.shape = build_circle_shape(v);
}
static fromJSON(j) {
const r = new TubePathStyle();
r.fromJSON(j);
return r;
}
/**
*
* @param {string|{r:number,g:number,b:number}} color
* @param material_type
* @param material
* @param opacity
* @param width
* @param radial_resolution
* @param resolution
* @param cast_shadow
* @param receive_shadow
* @param path_mask
* @param cap_type
* @param shape
* @param path_normal
* @param path_normal_type
*/
fromJSON({
color = DEFAULT_COLOR,
material_type,
material,
opacity = 1,
width = 1,
/**
* @deprecated
*/
radial_resolution = 16,
resolution = 10,
cast_shadow = false,
receive_shadow = false,
path_mask = [0, 1],
cap_type = CapType.None,
shape,
path_normal = Vector3.up,
path_normal_type = PathNormalType.Automatic
}) {
assert.enum(material_type, TubeMaterialType, 'material_type');
assert.isNumber(opacity, 'opacity');
assert.isNumber(width, 'width');
assert.isNumber(resolution, 'resolution');
assert.isBoolean(cast_shadow, 'cast_shadow');
assert.isBoolean(receive_shadow, 'receive_shadow');
assert.defined(path_mask, 'path_mask');
assert.notNull(path_mask, 'path_mask');
assert.greaterThanOrEqual(path_mask.length, 2, 'path_mask length bust be at least 2');
assert.ok(path_mask.length % 2 === 0, 'path_mask length bust be multiple of 2');
assert.enum(cap_type, CapType, 'cap_type');
assert.enum(path_normal_type, PathNormalType, 'path_normal_type');
if (shape === undefined) {
// legacy API, using circle
assert.isNumber(radial_resolution, 'radial_resolution');
shape = build_circle_shape(radial_resolution);
}
this.shape = shape;
if (typeof color === 'string') {
this.color.parse(color);
} else {
this.color.fromJSON(color);
}
this.material_type = material_type;
this.opacity = opacity;
this.width = width;
this.resolution = resolution;
this.cast_shadow = cast_shadow;
this.receive_shadow = receive_shadow;
this.path_mask = path_mask;
this.cap_type = cap_type;
switch (material_type) {
case TubeMaterialType.Matcap:
this.material = new MatcapMaterialDefinition();
break;
case TubeMaterialType.Standard:
this.material = new StandardMaterialDefinition();
break;
case TubeMaterialType.Basic:
this.material = new BasicMaterialDefinition();
break;
default:
throw new Error(`Unsupported material type '${material_type}'`);
}
this.material.fromJSON(material);
this.path_normal.fromJSON(path_normal);
this.path_normal_type = path_normal_type;
}
}
/**
*
* @param {number} radial_segments
* @returns {Float32Array}
*/
function build_circle_shape(radial_segments) {
const shape = new Float32Array(2 * radial_segments);
for (let i = 0; i < radial_segments; i++) {
const angle = Math.PI * 2 - Math.PI * 2 * (i / radial_segments);
const i2 = i * 2;
shape[i2] = Math.cos(angle);
shape[i2 + 1] = Math.sin(angle);
}
return shape;
}