@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
153 lines • 5.86 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { LOD as ThreeLOD, Object3D, Vector3 } from "three";
import { serializable } from "../engine/engine_serialization_decorator.js";
import { getParam } from "../engine/engine_utils.js";
import { Behaviour } from "./Component.js";
import { Renderer } from "./Renderer.js";
const debug = getParam("debuglods");
const noLods = getParam("nolods");
var LODFadeMode;
(function (LODFadeMode) {
LODFadeMode[LODFadeMode["None"] = 0] = "None";
LODFadeMode[LODFadeMode["CrossFade"] = 1] = "CrossFade";
LODFadeMode[LODFadeMode["SpeedTree"] = 2] = "SpeedTree";
})(LODFadeMode || (LODFadeMode = {}));
export class LODModel {
screenRelativeTransitionHeight;
distance;
renderers;
}
__decorate([
serializable()
], LODModel.prototype, "screenRelativeTransitionHeight", void 0);
__decorate([
serializable()
], LODModel.prototype, "distance", void 0);
__decorate([
serializable(Renderer)
], LODModel.prototype, "renderers", void 0);
class LOD {
model;
get renderers() { return this.model.renderers; }
constructor(model) {
this.model = model;
}
}
/**
* LODGroup allows to create a group of LOD levels for an object.
* @category Rendering
* @group Components
*/
export class LODGroup extends Behaviour {
fadeMode = LODFadeMode.None;
localReferencePoint = undefined;
lodCount = 0;
size = 0;
animateCrossFading = false;
lodModels;
_lods = [];
_settings = [];
// https://threejs.org/docs/#api/en/objects/LOD
_lodsHandler;
start() {
if (debug)
console.log("LODGROUP", this.name, this.lodModels, this);
if (noLods)
return;
if (this._lodsHandler)
return;
if (!this.gameObject)
return;
if (this.lodModels && Array.isArray(this.lodModels)) {
const renderers = [];
for (const model of this.lodModels) {
const lod = new LOD(model);
this._lods.push(lod);
for (const rend of lod.renderers) {
if (!renderers.includes(rend))
renderers.push(rend);
}
}
this._lodsHandler = new Array();
for (let i = 0; i < renderers.length; i++) {
const handler = new ThreeLOD();
this._lodsHandler.push(handler);
this.gameObject.add(handler);
}
const empty = new Object3D();
empty.name = "Cull " + this.name;
for (let i = 0; i < renderers.length; i++) {
const rend = renderers[i];
const handler = this._lodsHandler[i];
const obj = rend.gameObject;
if (debug)
console.log(i, obj.name);
for (const lod of this._lods) {
const dist = lod.model.distance;
// get object to be lodded, it can be empty
let object = null;
if (lod.renderers.includes(rend)) {
object = obj;
}
else {
object = empty;
}
if (object.type === "Group") {
console.warn(`LODGroup ${this.name}: Group or MultiMaterial object's are not supported as LOD object: ${object.name}`);
continue;
}
if (debug)
console.log("LEVEL", object.name, dist);
handler.autoUpdate = false;
this.onAddLodLevel(handler, object, lod.model.distance);
}
}
}
}
onAfterRender() {
if (!this.gameObject)
return;
if (!this._lodsHandler)
return;
const cam = this.context.mainCamera;
if (!cam)
return;
for (const h of this._lodsHandler) {
h.update(cam);
const levelIndex = h.getCurrentLevel();
const level = h.levels[levelIndex];
h.layers.mask = level.object.layers.mask;
}
}
onAddLodLevel(lod, obj, dist) {
if (obj === this.gameObject) {
console.warn("LODGroup component must be on parent object and not mesh directly at the moment", obj.name, obj);
return;
}
lod.addLevel(obj, dist * this._distanceFactor, .01);
const setting = { lod: lod, levelIndex: lod.levels.length - 1, distance: dist };
this._settings.push(setting);
}
_distanceFactor = 1;
distanceFactor(factor) {
if (factor === this._distanceFactor)
return;
this._distanceFactor = factor;
for (const setting of this._settings) {
const level = setting.lod.levels[setting.levelIndex];
level.distance = setting.distance * factor;
}
}
}
__decorate([
serializable(Vector3)
], LODGroup.prototype, "localReferencePoint", void 0);
__decorate([
serializable(LODModel)
], LODGroup.prototype, "lodModels", void 0);
//# sourceMappingURL=LODGroup.js.map