UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

373 lines (372 loc) 11 kB
"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; } }