vtt-mapper/src/assets/asset.class.ts

157 lines
6.1 KiB
TypeScript

import * as Three from 'three';
import * as CONST from '../consts';
import { AABB } from '../physics/common';
import Quadtree from '../physics/quadtree.class';
import { FreeList, clamp } from '../common';
const _mat = new Three.Matrix4();
export default class Asset
{
selected: boolean = false;
#layer: number;
#aabb: AABB;
#posX: number;
#posY: number;
#rot: number;
#scaleX: number;
#scaleY: number;
#sin: number;
#cos: number;
#index: number;
#quad?: number;
static instance: Three.InstancedMesh = new Three.InstancedMesh(CONST.QUAD, new Three.MeshBasicMaterial({ color: new Three.Color(0xffffff), side: Three.DoubleSide }), 1000000);
static quadtree: Quadtree = new Quadtree({ x1: -CONST.RESOLUTION_X / 2, x2: CONST.RESOLUTION_X / 2, y1: -CONST.RESOLUTION_Y / 2, y2: CONST.RESOLUTION_Y / 2 }, 6, 10);
static assets: FreeList<Asset> = new FreeList<Asset>();
constructor(posX?: number, posY?: number, scaleX?: number, scaleY?: number, rotation?: number, layer?: number)
{
this.#posX = posX ?? 0, this.#posY = posY ?? 0, this.#scaleX = scaleX ?? 0, this.#scaleY = scaleY ?? 0;
this.#rot = rotation ?? 0, this.#cos = Math.cos(this.#rot), this.#sin = Math.sin(this.#rot);
this.#layer = layer ?? 0;
this.#index = Asset.assets.insert(this);
console.log(this);
Asset.instance.instanceMatrix.setComponent(this.#index, 0, this.#cos * this.#scaleX);
Asset.instance.instanceMatrix.setComponent(this.#index, 1, this.#sin * this.#scaleX);
Asset.instance.instanceMatrix.setComponent(this.#index, 4, -this.#sin * this.#scaleY);
Asset.instance.instanceMatrix.setComponent(this.#index, 5, this.#cos * this.#scaleY);
Asset.instance.instanceMatrix.setComponent(this.#index, 12, this.#posX);
Asset.instance.instanceMatrix.setComponent(this.#index, 13, this.#posY);
Asset.instance.instanceMatrix.addUpdateRange(this.#index * 16, 16);
Asset.instance.instanceMatrix.needsUpdate = true;
this.#aabb = {
x1: -(this.#scaleX * Math.abs(this.#cos) + this.#scaleY * Math.abs(this.#sin)) / 2 + this.#posX,
x2: (this.#scaleX * Math.abs(this.#cos) + this.#scaleY * Math.abs(this.#sin)) / 2 + this.#posX,
y1: -(this.#scaleX * Math.abs(this.#sin) + this.#scaleY * Math.abs(this.#cos)) / 2 + this.#posY,
y2: (this.#scaleX * Math.abs(this.#sin) + this.#scaleY * Math.abs(this.#cos)) / 2 + this.#posY,
}
}
get aabb(): AABB {
return this.#aabb;
}
get layer(): number {
return this.#layer;
}
get posX(): number {
return this.#posX;
}
get posY(): number {
return this.#posY;
}
get rot(): number {
return this.#rot;
}
get scaleX(): number {
return this.#scaleX;
}
get scaleY(): number {
return this.#scaleY;
}
insert(): Asset
{
this.#quad = Asset.quadtree.insert(this.#index, this.#aabb);
return this;
}
remove(): Asset
{
this.#quad !== undefined && Asset.quadtree.remove(this.#quad);
Asset.assets.erase(this.#index);
Asset.instance.setMatrixAt(this.#index, _mat);
Asset.instance.instanceMatrix.addUpdateRange(this.#index * 16, 16);
Asset.instance.instanceMatrix.needsUpdate = true;
return this;
}
update(updateQuad: boolean = true): Asset
{
Asset.instance.instanceMatrix.needsUpdate = true;
if(updateQuad)
{
this.#quad !== undefined && Asset.quadtree.remove(this.#quad);
this.#quad = Asset.quadtree.insert(this.#index, this.#aabb);
}
return this;
}
moveTo(x: number, y: number): Asset
{
this.#aabb.x1 -= this.#posX - x;
this.#aabb.x2 -= this.#posX - x;
this.#aabb.y1 -= this.#posY - y;
this.#aabb.y2 -= this.#posY - y;
this.#posX = x, this.#posY = y;
Asset.instance.instanceMatrix.setComponent(this.#index, 12, x);
Asset.instance.instanceMatrix.setComponent(this.#index, 13, y);
return this;
}
rotateTo(rad: number): Asset
{
this.#rot = (rad + Math.PI) % (2*Math.PI) - Math.PI, this.#cos = Math.cos(this.#rot), this.#sin = Math.sin(this.#rot);
Asset.instance.instanceMatrix.setComponent(this.#index, 0, this.#cos * this.#scaleX);
Asset.instance.instanceMatrix.setComponent(this.#index, 1, this.#sin * this.#scaleX);
Asset.instance.instanceMatrix.setComponent(this.#index, 4, -this.#sin * this.#scaleY);
Asset.instance.instanceMatrix.setComponent(this.#index, 5, this.#cos * this.#scaleY);
this.#aabb.x1 = -(this.#scaleX * Math.abs(this.#cos) + this.#scaleY * Math.abs(this.#sin)) / 2 + this.#posX;
this.#aabb.x2 = (this.#scaleX * Math.abs(this.#cos) + this.#scaleY * Math.abs(this.#sin)) / 2 + this.#posX;
this.#aabb.y1 = -(this.#scaleX * Math.abs(this.#sin) + this.#scaleY * Math.abs(this.#cos)) / 2 + this.#posY;
this.#aabb.y2 = (this.#scaleX * Math.abs(this.#sin) + this.#scaleY * Math.abs(this.#cos)) / 2 + this.#posY;
return this;
}
matchAABB(aabb: AABB): Asset
{
const oldAABB = this.#aabb;
this.#aabb = aabb;
this.#posX = this.#aabb.x1 + (this.#aabb.x2 - this.#aabb.x1) / 2, this.#posY = this.#aabb.y1 + (this.#aabb.y2 - this.#aabb.y1) / 2;
this.#scaleX *= (this.#aabb.x2 - this.#aabb.x1) / (oldAABB.x2 - oldAABB.x1), this.#scaleY *= (this.#aabb.y2 - this.#aabb.y1) / (oldAABB.y2 - oldAABB.y1);
console.log(this.#posX, this.#posY, this.#scaleX, this.#scaleY);
Asset.instance.instanceMatrix.setComponent(this.#index, 0, this.#cos * this.#scaleX);
Asset.instance.instanceMatrix.setComponent(this.#index, 1, this.#sin * this.#scaleX);
Asset.instance.instanceMatrix.setComponent(this.#index, 4, -this.#sin * this.#scaleY);
Asset.instance.instanceMatrix.setComponent(this.#index, 5, this.#cos * this.#scaleY);
Asset.instance.instanceMatrix.setComponent(this.#index, 12, this.#posX);
Asset.instance.instanceMatrix.setComponent(this.#index, 13, this.#posY);
return this;
}
}