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 = new FreeList(); 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; } }