Skip to content

Improve random point algorithm #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"ngx-color": "^7.3.3",
"ngx-color-picker": "^12.0.1",
"ngx-perfect-scrollbar": "^10.1.1",
"poisson-disk-sampling": "^2.3.1",
"rxjs": "^6.6.7",
"rxjs-compat": "^6.6.7",
"save": "^2.9.0",
Expand Down
84 changes: 69 additions & 15 deletions src/app/modules/tv-map/models/prop-polygons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import { SceneService } from 'app/core/services/scene.service';
import { CatmullRomSpline } from 'app/core/shapes/catmull-rom-spline';
import { AnyControlPoint } from 'app/modules/three-js/objects/control-point';
import { AssetDatabase } from 'app/services/asset-database';
import { Group, InstancedMesh, Matrix4, Mesh, MeshBasicMaterial, Object3D, Shape, ShapeGeometry, Triangle, Vector2 } from 'three';
import { Group, InstancedMesh, Matrix4, Mesh, MeshBasicMaterial, Object3D, Shape, ShapeGeometry, Triangle, Vector2, Vector3 } from 'three';
import { Maths } from 'app/utils/maths';

import earcut from 'earcut';
import PoissonDiskSampling from 'poisson-disk-sampling';

export class PropPolygon {

Expand Down Expand Up @@ -159,28 +160,30 @@ export class PropPolygon {

addInstancesToMeshes ( count: number, face: number[], instancedMeshes: InstancedMesh[], instanceCounter: number ): void {

function randomInTriangle ( v1, v2, v3 ) {
// function randomInTriangle ( v1, v2, v3 ) {

const r1 = Math.random();
// const r1 = Math.random();

const r2 = Math.sqrt( Math.random() );
// const r2 = Math.sqrt( Math.random() );

const a = 1 - r2;
// const a = 1 - r2;

const b = r2 * ( 1 - r1 );
// const b = r2 * ( 1 - r1 );

const c = r1 * r2;
// const c = r1 * r2;

return ( v1.clone().multiplyScalar( a ) ).add( v2.clone().multiplyScalar( b ) ).add( v3.clone().multiplyScalar( c ) );
}
// return ( v1.clone().multiplyScalar( a ) ).add( v2.clone().multiplyScalar( b ) ).add( v3.clone().multiplyScalar( c ) );
// }

const v0 = this.spline.controlPointPositions[ face[ 0 ] ];
const v1 = this.spline.controlPointPositions[ face[ 1 ] ];
const v2 = this.spline.controlPointPositions[ face[ 2 ] ];

const randomPoints = this.generateRandomPointsInTriangle( v0, v1, v2, this.density );

for ( let i = 0; i < count; i++ ) {
for ( let i = 0; i < randomPoints.length; i++ ) {

const position = randomInTriangle(
this.spline.controlPointPositions[ face[ 0 ] ],
this.spline.controlPointPositions[ face[ 1 ] ],
this.spline.controlPointPositions[ face[ 2 ] ]
);
const position = new Vector3( randomPoints[ i ].x, randomPoints[ i ].y, 0 );

instancedMeshes.forEach( instancedMesh => {

Expand Down Expand Up @@ -319,6 +322,57 @@ export class PropPolygon {
return meshesAndMaterials;
}

private generateRandomPointsInTriangle ( v0, v1, v2, density ): {
x: number;
y: number;
}[] {

// Calculate the bounding box
const minX = Math.min( v0.x, v1.x, v2.x );
const maxX = Math.max( v0.x, v1.x, v2.x );
const minY = Math.min( v0.y, v1.y, v2.y );
const maxY = Math.max( v0.y, v1.y, v2.y );

const pds = new PoissonDiskSampling( {
shape: [ maxX - minX, maxY - minY ],
minDistance: 2 * density,
maxDistance: 10 * density,
tries: 30,
} );

const points = pds.fill();

// Filter out points that are not inside the triangle
const pointsInsideTriangle = points.filter( ( point ) => {
const transformedPoint = {
x: point[ 0 ] + minX,
y: point[ 1 ] + minY,
};
return this.pointInsideTriangle( transformedPoint, v0, v1, v2 );
} );

// Transform points to the triangle's local coordinate system
const transformedPoints = pointsInsideTriangle.map( ( point ) => {
return {
x: point[ 0 ] + minX,
y: point[ 1 ] + minY,
};
} );

return transformedPoints;
}

private pointInsideTriangle ( point, v0, v1, v2 ) {

const area = ( v0.x * ( v1.y - v2.y ) + v1.x * ( v2.y - v0.y ) + v2.x * ( v0.y - v1.y ) );

const s = ( v0.y * v2.x - v0.x * v2.y + ( v2.y - v0.y ) * point.x + ( v0.x - v2.x ) * point.y ) / area;

const t = ( v0.y * v1.x - v0.x * v1.y + ( v1.y - v0.y ) * point.x + ( v0.x - v1.x ) * point.y ) / area;

return s >= 0 && t >= 0 && ( 1 - s - t ) >= 0;
}

addControlPoint ( cp: AnyControlPoint ) {

( this.spline as CatmullRomSpline ).add( cp );
Expand Down