123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- import { Tools } from "babylonjs/Misc/tools";
- import { TmpVectors, Vector3 } from "babylonjs/Maths/math";
- import { float } from "babylonjs/types";
- import { VolumeBasedPanel } from "./volumeBasedPanel";
- import { Control3D } from "./control3D";
- import { Container3D } from "./container3D";
- /**
- * Class used to create a container panel where items get randomized planar mapping
- */
- export class ScatterPanel extends VolumeBasedPanel {
- private _iteration = 100.0;
- /**
- * Gets or sets the number of iteration to use to scatter the controls (100 by default)
- */
- public get iteration(): float {
- return this._iteration;
- }
- public set iteration(value: float) {
- if (this._iteration === value) {
- return;
- }
- this._iteration = value;
- Tools.SetImmediate(() => {
- this._arrangeChildren();
- });
- }
- protected _mapGridNode(control: Control3D, nodePosition: Vector3) {
- let mesh = control.mesh;
- let newPos = this._scatterMapping(nodePosition);
- if (!mesh) {
- return;
- }
- switch (this.orientation) {
- case Container3D.FACEORIGIN_ORIENTATION:
- case Container3D.FACEFORWARD_ORIENTATION:
- mesh.lookAt(new Vector3(0, 0, 1));
- break;
- case Container3D.FACEFORWARDREVERSED_ORIENTATION:
- case Container3D.FACEORIGINREVERSED_ORIENTATION:
- mesh.lookAt(new Vector3(0, 0, -1));
- break;
- }
- control.position = newPos;
- }
- private _scatterMapping(source: Vector3): Vector3 {
- source.x = (1.0 - Math.random() * 2.0) * this._cellWidth;
- source.y = (1.0 - Math.random() * 2.0) * this._cellHeight;
- return source;
- }
- protected _finalProcessing() {
- var meshes = [];
- for (var child of this._children) {
- if (!child.mesh) {
- continue;
- }
- meshes.push(child.mesh);
- }
- for (var count = 0; count < this._iteration; count++) {
- meshes.sort((a, b) => {
- let distance1 = a.position.lengthSquared();
- let distance2 = b.position.lengthSquared();
- if (distance1 < distance2) {
- return 1;
- } else if (distance1 > distance2) {
- return -1;
- }
- return 0;
- });
- let radiusPaddingSquared = Math.pow(this.margin, 2.0);
- let cellSize = Math.max(this._cellWidth, this._cellHeight);
- let difference2D = TmpVectors.Vector2[0];
- let difference = TmpVectors.Vector3[0];
- for (let i = 0; i < meshes.length - 1; i++) {
- for (let j = i + 1; j < meshes.length; j++) {
- if (i != j) {
- meshes[j].position.subtractToRef(meshes[i].position, difference);
- // Ignore Z axis
- difference2D.x = difference.x;
- difference2D.y = difference.y;
- let combinedRadius = cellSize;
- let distance = difference2D.lengthSquared() - radiusPaddingSquared;
- let minSeparation = Math.min(distance, radiusPaddingSquared);
- distance -= minSeparation;
- if (distance < (Math.pow(combinedRadius, 2.0))) {
- difference2D.normalize();
- difference.scaleInPlace((combinedRadius - Math.sqrt(distance)) * 0.5);
- meshes[j].position.addInPlace(difference);
- meshes[i].position.subtractInPlace(difference);
- }
- }
- }
- }
- }
- }
- }
|