@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
373 lines (372 loc) • 11 kB
JavaScript
"use strict";
import { Vector4, Vector3, Vector2 } from "three";
import { Attribute, CoreAttribute } from "../../Attribute";
import { CoreEntityWithObject } from "../../CoreEntity";
import { isArray } from "../../../Type";
import {
DOT,
COMPONENT_INDICES,
AttribClass,
AttribType
} from "../../Constant";
import { TypeAssert } from "../../../../engine/poly/Assert";
import { uniqRelatedEntityIds } from "../utils/Common";
function _warnOverloadRequired(functionName) {
console.warn(`CorePrimitive.${functionName} needs to be overloaded`);
}
const _ids = [];
export class CorePrimitive extends CoreEntityWithObject {
builder() {
return void 0;
}
static entitiesCount(object) {
return 0;
}
static addAttribute(object, attribName, attribute) {
_warnOverloadRequired("addAttribute");
}
static addNumericAttribute(object, attribName, size = 1, defaultValue = 0) {
_warnOverloadRequired("addNumericAttribute");
}
static attributes(object) {
_warnOverloadRequired("attributes");
return;
}
attributes() {
if (!this._object) {
return;
}
return this.constructor.attributes(this._object);
}
static attribute(object, attribName) {
const attributes = this.attributes(object);
if (!attributes) {
return;
}
return attributes[attribName];
}
attribute(attribName) {
if (!this._object) {
return;
}
return this.constructor.attribute(this._object, attribName);
}
static renameAttribute(object, oldName, newName) {
const attributes = this.attributes(object);
if (!attributes) {
return;
}
const attribute = this.attribute(object, oldName);
if (!attribute) {
return;
}
attributes[newName] = attribute;
delete attributes[oldName];
}
static deleteAttribute(object, attribName) {
const attributes = this.attributes(object);
if (!attributes) {
return;
}
delete attributes[attribName];
}
static attribSize(object, attribName) {
const attributes = this.attributes(object);
if (!attributes) {
return -1;
}
attribName = CoreAttribute.remapName(attribName);
return attributes[attribName].itemSize || 0;
}
attribSize(attribName) {
if (!this._object) {
return 0;
}
return this.constructor.attribSize(this._object, attribName);
}
static hasAttribute(object, attribName) {
const remappedName = CoreAttribute.remapName(attribName);
return this.attributes(object) ? this.attributes(object)[remappedName] != null : false;
}
hasAttribute(attribName) {
if (!this._object) {
return false;
}
return this.constructor.hasAttribute(this._object, attribName);
}
static attributeNames(object) {
const attributes = this.attributes(object);
if (!attributes) {
return [];
}
return Object.keys(attributes);
}
static attributeNamesMatchingMask(object, masksString) {
return CoreAttribute.attribNamesMatchingMask(masksString, this.attributeNames(object));
}
static attribValue(object, index, attribName, target) {
if (attribName === Attribute.PRIMITIVE_INDEX) {
return index;
}
let componentName = null;
let componentIndex = null;
if (attribName[attribName.length - 2] === DOT) {
componentName = attribName[attribName.length - 1];
componentIndex = COMPONENT_INDICES[componentName];
attribName = attribName.substring(0, attribName.length - 2);
}
const remapedName = CoreAttribute.remapName(attribName);
if (remapedName == Attribute.POSITION) {
return this.position(object, index, target);
}
if (remapedName == Attribute.NORMAL) {
return this.normal(object, index, target);
}
const attrib = this.attribute(object, remapedName);
if (attrib) {
const { array } = attrib;
const itemSize = attrib.itemSize;
const startIndex = index * itemSize;
if (componentIndex == null) {
switch (itemSize) {
case 1:
return array[startIndex];
break;
case 2:
target = target || new Vector2();
target.fromArray(array, startIndex);
return target;
break;
case 3:
target = target || new Vector3();
target.fromArray(array, startIndex);
return target;
break;
case 4:
target = target || new Vector4();
target.fromArray(array, startIndex);
return target;
break;
default:
throw `size not valid (${itemSize})`;
}
} else {
switch (itemSize) {
case 1:
return array[startIndex];
break;
default:
return array[startIndex + componentIndex];
}
}
} else {
const attributesDict = this.attributes(object) || {};
const attribNames = Object.keys(attributesDict);
const message = `attrib ${attribName} not found. availables are: ${attribNames.join(",")}`;
console.warn(message);
throw message;
}
}
attribValue(attribName, target) {
if (!this._object) {
return 0;
}
return this.constructor.attribValue(this._object, this._index, attribName, target);
}
attribValueNumber(attribName) {
const attrib = this.attribute(attribName);
if (!attrib) {
return 0;
}
return attrib.array[this._index];
}
attribValueVector2(attribName, target) {
const attrib = this.attribute(attribName);
if (!attrib) {
return;
}
target.fromArray(attrib.array, this._index * 2);
return target;
}
attribValueVector3(attribName, target) {
const attrib = this.attribute(attribName);
if (!attrib) {
return;
}
target.fromArray(attrib.array, this._index * 3);
return target;
}
attribValueVector4(attribName, target) {
const attrib = this.attribute(attribName);
if (!attrib) {
return;
}
target.fromArray(attrib.array, this._index * 4);
return target;
}
static attribType(object, attribName) {
const attribute = object ? this.attribute(object, attribName) : null;
if (attribute && (attribute == null ? void 0 : attribute.isString) == true) {
return AttribType.STRING;
} else {
return AttribType.NUMERIC;
}
}
attribType(attribName) {
return this.constructor.attribType(this._object, attribName);
}
static stringAttribValue(object, index, attribName) {
return this.attribValue(object, index, attribName);
}
stringAttribValue(attribName) {
return this.attribValue(attribName);
}
// setPosition(newPosition: Vector3) {
// this.setAttribValueFromVector3(Attribute.POSITION, newPosition);
// }
// setNormal(newNormal: Vector3) {
// return this.setAttribValueFromVector3(Attribute.NORMAL, newNormal);
// }
static position(object, primitiveIndex, target) {
_warnOverloadRequired("position");
return target;
}
static normal(object, primitiveIndex, target) {
_warnOverloadRequired("normal");
return target;
}
static computeVertexNormalsIfAttributeVersionChanged(object) {
_warnOverloadRequired("computeVertexNormalsIfAttributeVersionChanged");
}
setAttribValue(attribName, value) {
const attrib = this.attribute(attribName);
if (!attrib) {
console.warn(`no attribute ${attribName}`);
return;
}
const array = attrib.array;
const attribSize = attrib.itemSize;
if (isArray(value)) {
for (let i = 0; i < attribSize; i++) {
array[this._index * attribSize + i] = value[i];
}
return;
}
switch (attribSize) {
case 1:
array[this._index] = value;
break;
case 2:
const v2 = value;
const i2 = this._index * 2;
array[i2 + 0] = v2.x;
array[i2 + 1] = v2.y;
break;
case 3:
const isColor = value.r != null;
const i3 = this._index * 3;
if (isColor) {
const col = value;
array[i3 + 0] = col.r;
array[i3 + 1] = col.g;
array[i3 + 2] = col.b;
} else {
const v3 = value;
array[i3 + 0] = v3.x;
array[i3 + 1] = v3.y;
array[i3 + 2] = v3.z;
}
break;
case 4:
const v4 = value;
const i4 = this._index * 4;
array[i4 + 0] = v4.x;
array[i4 + 1] = v4.y;
array[i4 + 2] = v4.z;
array[i4 + 3] = v4.w;
break;
default:
console.warn(`CorePrimitive.setAttribValue does not yet allow attribSize ${attribSize}`);
throw `attrib size ${attribSize} not implemented`;
}
}
setAttribValueFromNumber(attribName, value) {
const attrib = this.attribute(attribName);
if (!attrib) {
return;
}
const array = attrib.array;
array[this._index] = value;
}
setAttribValueFromVector2(attribName, value) {
const attrib = this.attribute(attribName);
if (!attrib || attrib.isString == true) {
return;
}
value.toArray(attrib.array, this._index * 2);
}
setAttribValueFromVector3(attribName, value) {
const attrib = this.attribute(attribName);
if (!attrib || attrib.isString == true) {
return;
}
value.toArray(attrib.array, this._index * 3);
}
setAttribValueFromVector4(attribName, value) {
const attrib = this.attribute(attribName);
if (!attrib || attrib.isString == true) {
return;
}
value.toArray(attrib.array, this._index * 4);
}
//
//
// RELATED ENTITIES
//
//
static relatedPointIds(object, pointIndex, target, traversedRelatedEntityData) {
const ids = traversedRelatedEntityData ? traversedRelatedEntityData[AttribClass.VERTEX].ids : _ids;
this.relatedVertexIds(object, pointIndex, ids);
uniqRelatedEntityIds(
ids,
(vertexId, relatedEntityIds) => {
this.relatedVertexClass(object).relatedPointIds(object, vertexId, relatedEntityIds);
},
target
);
}
static relatedPointClass(object) {
return this.relatedVertexClass(object).relatedPointClass(object);
}
relatedEntities(attribClass, coreGroup, target, traversedRelatedEntityData) {
switch (attribClass) {
case AttribClass.POINT: {
this.relatedPoints(target, traversedRelatedEntityData);
return;
}
case AttribClass.VERTEX: {
this.relatedVertices(target, traversedRelatedEntityData);
return;
}
case AttribClass.PRIMITIVE: {
target.length = 1;
target[0] = this;
return;
}
case AttribClass.OBJECT: {
this.relatedObjects(target, traversedRelatedEntityData);
return;
}
case AttribClass.CORE_GROUP: {
target.length = 1;
target[0] = coreGroup;
return;
}
}
TypeAssert.unreachable(attribClass);
}
static graph(object) {
console.warn("CorePrimitive.graph needs to be overriden");
return void 0;
}
}