新增polygonmesh
This commit is contained in:
31
demo/libs/framework/framework.d.ts
vendored
31
demo/libs/framework/framework.d.ts
vendored
@@ -255,6 +255,25 @@ declare class Camera extends Component {
|
|||||||
updateMatrixes(): void;
|
updateMatrixes(): void;
|
||||||
destory(): void;
|
destory(): void;
|
||||||
}
|
}
|
||||||
|
declare class Mesh extends Component {
|
||||||
|
private _verts;
|
||||||
|
private _primitiveCount;
|
||||||
|
private _triangles;
|
||||||
|
private _topLeftVertPosition;
|
||||||
|
private _width;
|
||||||
|
private _height;
|
||||||
|
initialize(): void;
|
||||||
|
setVertPosition(positions: Vector2[]): this;
|
||||||
|
setTriangles(triangles: number[]): this;
|
||||||
|
recalculateBounds(): this;
|
||||||
|
}
|
||||||
|
declare class VertexPosition {
|
||||||
|
position: Vector2;
|
||||||
|
constructor(position: Vector2);
|
||||||
|
}
|
||||||
|
declare class PolygonMesh extends Mesh {
|
||||||
|
constructor(points: Vector2[], arePointsCCW?: boolean);
|
||||||
|
}
|
||||||
declare class EntitySystem {
|
declare class EntitySystem {
|
||||||
private _scene;
|
private _scene;
|
||||||
private _entities;
|
private _entities;
|
||||||
@@ -455,3 +474,15 @@ declare class Collisions {
|
|||||||
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
||||||
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
||||||
}
|
}
|
||||||
|
declare class Triangulator {
|
||||||
|
triangleIndices: number[];
|
||||||
|
private _triPrev;
|
||||||
|
private _triNext;
|
||||||
|
triangulate(points: Vector2[], arePointsCCW?: boolean): void;
|
||||||
|
private initialize;
|
||||||
|
static testPointTriangle(point: Vector2, a: Vector2, b: Vector2, c: Vector2): boolean;
|
||||||
|
}
|
||||||
|
declare class Vector2Ext {
|
||||||
|
static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2): boolean;
|
||||||
|
static cross(u: Vector2, v: Vector2): number;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1369,6 +1369,62 @@ var Camera = (function (_super) {
|
|||||||
};
|
};
|
||||||
return Camera;
|
return Camera;
|
||||||
}(Component));
|
}(Component));
|
||||||
|
var Mesh = (function (_super) {
|
||||||
|
__extends(Mesh, _super);
|
||||||
|
function Mesh() {
|
||||||
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
}
|
||||||
|
Mesh.prototype.initialize = function () {
|
||||||
|
};
|
||||||
|
Mesh.prototype.setVertPosition = function (positions) {
|
||||||
|
var createVerts = !this._verts || this._verts.length != positions.length;
|
||||||
|
if (createVerts)
|
||||||
|
this._verts = new Array(positions.length);
|
||||||
|
for (var i = 0; i < this._verts.length; i++) {
|
||||||
|
this._verts[i] = new VertexPosition(positions[i]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Mesh.prototype.setTriangles = function (triangles) {
|
||||||
|
this._primitiveCount = triangles.length / 3;
|
||||||
|
this._triangles = triangles;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Mesh.prototype.recalculateBounds = function () {
|
||||||
|
this._topLeftVertPosition = new Vector2(Number.MAX_VALUE, Number.MAX_VALUE);
|
||||||
|
var max = new Vector2(Number.MIN_VALUE, Number.MIN_VALUE);
|
||||||
|
for (var i = 0; i < this._verts.length; i++) {
|
||||||
|
this._topLeftVertPosition.x = Math.min(this._topLeftVertPosition.x, this._verts[i].position.x);
|
||||||
|
this._topLeftVertPosition.y = Math.min(this._topLeftVertPosition.y, this._verts[i].position.y);
|
||||||
|
max.x = Math.max(max.x, this._verts[i].position.x);
|
||||||
|
max.y = Math.max(max.y, this._verts[i].position.y);
|
||||||
|
}
|
||||||
|
this._width = max.x - this._topLeftVertPosition.x;
|
||||||
|
this._height = max.y - this._topLeftVertPosition.y;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
return Mesh;
|
||||||
|
}(Component));
|
||||||
|
var VertexPosition = (function () {
|
||||||
|
function VertexPosition(position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
return VertexPosition;
|
||||||
|
}());
|
||||||
|
var PolygonMesh = (function (_super) {
|
||||||
|
__extends(PolygonMesh, _super);
|
||||||
|
function PolygonMesh(points, arePointsCCW) {
|
||||||
|
if (arePointsCCW === void 0) { arePointsCCW = true; }
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
var triangulator = new Triangulator();
|
||||||
|
triangulator.triangulate(points, arePointsCCW);
|
||||||
|
_this.setVertPosition(points);
|
||||||
|
_this.setTriangles(triangulator.triangleIndices);
|
||||||
|
_this.recalculateBounds();
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
return PolygonMesh;
|
||||||
|
}(Mesh));
|
||||||
var EntitySystem = (function () {
|
var EntitySystem = (function () {
|
||||||
function EntitySystem(matcher) {
|
function EntitySystem(matcher) {
|
||||||
this._entities = [];
|
this._entities = [];
|
||||||
@@ -2301,3 +2357,92 @@ var Collisions = (function () {
|
|||||||
};
|
};
|
||||||
return Collisions;
|
return Collisions;
|
||||||
}());
|
}());
|
||||||
|
var Triangulator = (function () {
|
||||||
|
function Triangulator() {
|
||||||
|
this.triangleIndices = [];
|
||||||
|
this._triPrev = new Array(12);
|
||||||
|
this._triNext = new Array(12);
|
||||||
|
}
|
||||||
|
Triangulator.prototype.triangulate = function (points, arePointsCCW) {
|
||||||
|
if (arePointsCCW === void 0) { arePointsCCW = true; }
|
||||||
|
var count = points.length;
|
||||||
|
this.initialize(count);
|
||||||
|
var iterations = 0;
|
||||||
|
var index = 0;
|
||||||
|
while (count > 3 && iterations < 500) {
|
||||||
|
iterations++;
|
||||||
|
var isEar = true;
|
||||||
|
var a = points[this._triPrev[index]];
|
||||||
|
var b = points[index];
|
||||||
|
var c = points[this._triNext[index]];
|
||||||
|
if (Vector2Ext.isTriangleCCW(a, b, c)) {
|
||||||
|
var k = this._triNext[this._triNext[index]];
|
||||||
|
do {
|
||||||
|
if (Triangulator.testPointTriangle(points[k], a, b, c)) {
|
||||||
|
isEar = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
k = this._triNext[k];
|
||||||
|
} while (k != this._triPrev[index]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isEar = false;
|
||||||
|
}
|
||||||
|
if (isEar) {
|
||||||
|
this.triangleIndices.push(this._triPrev[index]);
|
||||||
|
this.triangleIndices.push(index);
|
||||||
|
this.triangleIndices.push(this._triNext[index]);
|
||||||
|
this._triNext[this._triPrev[index]] = this._triNext[index];
|
||||||
|
this._triPrev[this._triNext[index]] = this._triPrev[index];
|
||||||
|
count--;
|
||||||
|
index = this._triPrev[index];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
index = this._triNext[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.triangleIndices.push(this._triPrev[index]);
|
||||||
|
this.triangleIndices.push(index);
|
||||||
|
this.triangleIndices.push(this._triNext[index]);
|
||||||
|
if (!arePointsCCW)
|
||||||
|
this.triangleIndices.reverse();
|
||||||
|
};
|
||||||
|
Triangulator.prototype.initialize = function (count) {
|
||||||
|
this.triangleIndices.length = 0;
|
||||||
|
if (this._triNext.length < count) {
|
||||||
|
this._triNext.reverse();
|
||||||
|
this._triNext = new Array(Math.max(this._triNext.length * 2, count));
|
||||||
|
}
|
||||||
|
if (this._triPrev.length < count) {
|
||||||
|
this._triPrev.reverse();
|
||||||
|
this._triPrev = new Array(Math.max(this._triPrev.length * 2, count));
|
||||||
|
}
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
this._triPrev[i] = i - 1;
|
||||||
|
this._triNext[i] = i + 1;
|
||||||
|
}
|
||||||
|
this._triPrev[0] = count - 1;
|
||||||
|
this._triNext[count - 1] = 0;
|
||||||
|
};
|
||||||
|
Triangulator.testPointTriangle = function (point, a, b, c) {
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, a), Vector2.subtract(b, a)) < 0)
|
||||||
|
return false;
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, b), Vector2.subtract(c, b)) < 0)
|
||||||
|
return false;
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, c), Vector2.subtract(a, c)) < 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
return Triangulator;
|
||||||
|
}());
|
||||||
|
var Vector2Ext = (function () {
|
||||||
|
function Vector2Ext() {
|
||||||
|
}
|
||||||
|
Vector2Ext.isTriangleCCW = function (a, center, c) {
|
||||||
|
return this.cross(Vector2.subtract(center, a), Vector2.subtract(c, center)) < 0;
|
||||||
|
};
|
||||||
|
Vector2Ext.cross = function (u, v) {
|
||||||
|
return u.y * v.x - u.x * v.y;
|
||||||
|
};
|
||||||
|
return Vector2Ext;
|
||||||
|
}());
|
||||||
|
|||||||
2
demo/libs/framework/framework.min.js
vendored
2
demo/libs/framework/framework.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -93,6 +93,11 @@ class Main extends eui.UILayer {
|
|||||||
protected createGameScene(): void {
|
protected createGameScene(): void {
|
||||||
let scene = SceneManager.createScene("main", new MainScene(this)).setActive();
|
let scene = SceneManager.createScene("main", new MainScene(this)).setActive();
|
||||||
let player = scene.createEntity("player");
|
let player = scene.createEntity("player");
|
||||||
|
player.addComponent(new PolygonMesh([new Vector2(0, 0),
|
||||||
|
new Vector2(10, 0),
|
||||||
|
new Vector2(10, 10),
|
||||||
|
new Vector2(0, 10),
|
||||||
|
new Vector2(0, 0)]));
|
||||||
player.addComponent(new SpawnComponent(EnemyType.worm));
|
player.addComponent(new SpawnComponent(EnemyType.worm));
|
||||||
// console.log(player.transform.position);
|
// console.log(player.transform.position);
|
||||||
}
|
}
|
||||||
|
|||||||
31
source/bin/framework.d.ts
vendored
31
source/bin/framework.d.ts
vendored
@@ -255,6 +255,25 @@ declare class Camera extends Component {
|
|||||||
updateMatrixes(): void;
|
updateMatrixes(): void;
|
||||||
destory(): void;
|
destory(): void;
|
||||||
}
|
}
|
||||||
|
declare class Mesh extends Component {
|
||||||
|
private _verts;
|
||||||
|
private _primitiveCount;
|
||||||
|
private _triangles;
|
||||||
|
private _topLeftVertPosition;
|
||||||
|
private _width;
|
||||||
|
private _height;
|
||||||
|
initialize(): void;
|
||||||
|
setVertPosition(positions: Vector2[]): this;
|
||||||
|
setTriangles(triangles: number[]): this;
|
||||||
|
recalculateBounds(): this;
|
||||||
|
}
|
||||||
|
declare class VertexPosition {
|
||||||
|
position: Vector2;
|
||||||
|
constructor(position: Vector2);
|
||||||
|
}
|
||||||
|
declare class PolygonMesh extends Mesh {
|
||||||
|
constructor(points: Vector2[], arePointsCCW?: boolean);
|
||||||
|
}
|
||||||
declare class EntitySystem {
|
declare class EntitySystem {
|
||||||
private _scene;
|
private _scene;
|
||||||
private _entities;
|
private _entities;
|
||||||
@@ -455,3 +474,15 @@ declare class Collisions {
|
|||||||
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
static isRectToPoint(rX: number, rY: number, rW: number, rH: number, point: Vector2): boolean;
|
||||||
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
static getSector(rX: number, rY: number, rW: number, rH: number, point: Vector2): PointSectors;
|
||||||
}
|
}
|
||||||
|
declare class Triangulator {
|
||||||
|
triangleIndices: number[];
|
||||||
|
private _triPrev;
|
||||||
|
private _triNext;
|
||||||
|
triangulate(points: Vector2[], arePointsCCW?: boolean): void;
|
||||||
|
private initialize;
|
||||||
|
static testPointTriangle(point: Vector2, a: Vector2, b: Vector2, c: Vector2): boolean;
|
||||||
|
}
|
||||||
|
declare class Vector2Ext {
|
||||||
|
static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2): boolean;
|
||||||
|
static cross(u: Vector2, v: Vector2): number;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1369,6 +1369,62 @@ var Camera = (function (_super) {
|
|||||||
};
|
};
|
||||||
return Camera;
|
return Camera;
|
||||||
}(Component));
|
}(Component));
|
||||||
|
var Mesh = (function (_super) {
|
||||||
|
__extends(Mesh, _super);
|
||||||
|
function Mesh() {
|
||||||
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
}
|
||||||
|
Mesh.prototype.initialize = function () {
|
||||||
|
};
|
||||||
|
Mesh.prototype.setVertPosition = function (positions) {
|
||||||
|
var createVerts = !this._verts || this._verts.length != positions.length;
|
||||||
|
if (createVerts)
|
||||||
|
this._verts = new Array(positions.length);
|
||||||
|
for (var i = 0; i < this._verts.length; i++) {
|
||||||
|
this._verts[i] = new VertexPosition(positions[i]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Mesh.prototype.setTriangles = function (triangles) {
|
||||||
|
this._primitiveCount = triangles.length / 3;
|
||||||
|
this._triangles = triangles;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Mesh.prototype.recalculateBounds = function () {
|
||||||
|
this._topLeftVertPosition = new Vector2(Number.MAX_VALUE, Number.MAX_VALUE);
|
||||||
|
var max = new Vector2(Number.MIN_VALUE, Number.MIN_VALUE);
|
||||||
|
for (var i = 0; i < this._verts.length; i++) {
|
||||||
|
this._topLeftVertPosition.x = Math.min(this._topLeftVertPosition.x, this._verts[i].position.x);
|
||||||
|
this._topLeftVertPosition.y = Math.min(this._topLeftVertPosition.y, this._verts[i].position.y);
|
||||||
|
max.x = Math.max(max.x, this._verts[i].position.x);
|
||||||
|
max.y = Math.max(max.y, this._verts[i].position.y);
|
||||||
|
}
|
||||||
|
this._width = max.x - this._topLeftVertPosition.x;
|
||||||
|
this._height = max.y - this._topLeftVertPosition.y;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
return Mesh;
|
||||||
|
}(Component));
|
||||||
|
var VertexPosition = (function () {
|
||||||
|
function VertexPosition(position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
return VertexPosition;
|
||||||
|
}());
|
||||||
|
var PolygonMesh = (function (_super) {
|
||||||
|
__extends(PolygonMesh, _super);
|
||||||
|
function PolygonMesh(points, arePointsCCW) {
|
||||||
|
if (arePointsCCW === void 0) { arePointsCCW = true; }
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
var triangulator = new Triangulator();
|
||||||
|
triangulator.triangulate(points, arePointsCCW);
|
||||||
|
_this.setVertPosition(points);
|
||||||
|
_this.setTriangles(triangulator.triangleIndices);
|
||||||
|
_this.recalculateBounds();
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
return PolygonMesh;
|
||||||
|
}(Mesh));
|
||||||
var EntitySystem = (function () {
|
var EntitySystem = (function () {
|
||||||
function EntitySystem(matcher) {
|
function EntitySystem(matcher) {
|
||||||
this._entities = [];
|
this._entities = [];
|
||||||
@@ -2301,3 +2357,92 @@ var Collisions = (function () {
|
|||||||
};
|
};
|
||||||
return Collisions;
|
return Collisions;
|
||||||
}());
|
}());
|
||||||
|
var Triangulator = (function () {
|
||||||
|
function Triangulator() {
|
||||||
|
this.triangleIndices = [];
|
||||||
|
this._triPrev = new Array(12);
|
||||||
|
this._triNext = new Array(12);
|
||||||
|
}
|
||||||
|
Triangulator.prototype.triangulate = function (points, arePointsCCW) {
|
||||||
|
if (arePointsCCW === void 0) { arePointsCCW = true; }
|
||||||
|
var count = points.length;
|
||||||
|
this.initialize(count);
|
||||||
|
var iterations = 0;
|
||||||
|
var index = 0;
|
||||||
|
while (count > 3 && iterations < 500) {
|
||||||
|
iterations++;
|
||||||
|
var isEar = true;
|
||||||
|
var a = points[this._triPrev[index]];
|
||||||
|
var b = points[index];
|
||||||
|
var c = points[this._triNext[index]];
|
||||||
|
if (Vector2Ext.isTriangleCCW(a, b, c)) {
|
||||||
|
var k = this._triNext[this._triNext[index]];
|
||||||
|
do {
|
||||||
|
if (Triangulator.testPointTriangle(points[k], a, b, c)) {
|
||||||
|
isEar = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
k = this._triNext[k];
|
||||||
|
} while (k != this._triPrev[index]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isEar = false;
|
||||||
|
}
|
||||||
|
if (isEar) {
|
||||||
|
this.triangleIndices.push(this._triPrev[index]);
|
||||||
|
this.triangleIndices.push(index);
|
||||||
|
this.triangleIndices.push(this._triNext[index]);
|
||||||
|
this._triNext[this._triPrev[index]] = this._triNext[index];
|
||||||
|
this._triPrev[this._triNext[index]] = this._triPrev[index];
|
||||||
|
count--;
|
||||||
|
index = this._triPrev[index];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
index = this._triNext[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.triangleIndices.push(this._triPrev[index]);
|
||||||
|
this.triangleIndices.push(index);
|
||||||
|
this.triangleIndices.push(this._triNext[index]);
|
||||||
|
if (!arePointsCCW)
|
||||||
|
this.triangleIndices.reverse();
|
||||||
|
};
|
||||||
|
Triangulator.prototype.initialize = function (count) {
|
||||||
|
this.triangleIndices.length = 0;
|
||||||
|
if (this._triNext.length < count) {
|
||||||
|
this._triNext.reverse();
|
||||||
|
this._triNext = new Array(Math.max(this._triNext.length * 2, count));
|
||||||
|
}
|
||||||
|
if (this._triPrev.length < count) {
|
||||||
|
this._triPrev.reverse();
|
||||||
|
this._triPrev = new Array(Math.max(this._triPrev.length * 2, count));
|
||||||
|
}
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
this._triPrev[i] = i - 1;
|
||||||
|
this._triNext[i] = i + 1;
|
||||||
|
}
|
||||||
|
this._triPrev[0] = count - 1;
|
||||||
|
this._triNext[count - 1] = 0;
|
||||||
|
};
|
||||||
|
Triangulator.testPointTriangle = function (point, a, b, c) {
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, a), Vector2.subtract(b, a)) < 0)
|
||||||
|
return false;
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, b), Vector2.subtract(c, b)) < 0)
|
||||||
|
return false;
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, c), Vector2.subtract(a, c)) < 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
return Triangulator;
|
||||||
|
}());
|
||||||
|
var Vector2Ext = (function () {
|
||||||
|
function Vector2Ext() {
|
||||||
|
}
|
||||||
|
Vector2Ext.isTriangleCCW = function (a, center, c) {
|
||||||
|
return this.cross(Vector2.subtract(center, a), Vector2.subtract(c, center)) < 0;
|
||||||
|
};
|
||||||
|
Vector2Ext.cross = function (u, v) {
|
||||||
|
return u.y * v.x - u.x * v.y;
|
||||||
|
};
|
||||||
|
return Vector2Ext;
|
||||||
|
}());
|
||||||
|
|||||||
2
source/bin/framework.min.js
vendored
2
source/bin/framework.min.js
vendored
File diff suppressed because one or more lines are too long
54
source/src/ECS/Components/Mesh.ts
Normal file
54
source/src/ECS/Components/Mesh.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
class Mesh extends Component {
|
||||||
|
private _verts: VertexPosition[];
|
||||||
|
private _primitiveCount: number;
|
||||||
|
private _triangles: number[];
|
||||||
|
private _topLeftVertPosition: Vector2;
|
||||||
|
private _width;
|
||||||
|
private _height;
|
||||||
|
|
||||||
|
public initialize() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public setVertPosition(positions: Vector2[]){
|
||||||
|
let createVerts = !this._verts || this._verts.length != positions.length;
|
||||||
|
if (createVerts)
|
||||||
|
this._verts = new Array(positions.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < this._verts.length; i ++){
|
||||||
|
this._verts[i] = new VertexPosition(positions[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setTriangles(triangles: number[]){
|
||||||
|
this._primitiveCount = triangles.length / 3;
|
||||||
|
this._triangles = triangles;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public recalculateBounds(){
|
||||||
|
this._topLeftVertPosition = new Vector2(Number.MAX_VALUE, Number.MAX_VALUE);
|
||||||
|
let max = new Vector2(Number.MIN_VALUE, Number.MIN_VALUE);
|
||||||
|
|
||||||
|
for (let i = 0; i < this._verts.length; i ++){
|
||||||
|
this._topLeftVertPosition.x = Math.min(this._topLeftVertPosition.x, this._verts[i].position.x);
|
||||||
|
this._topLeftVertPosition.y = Math.min(this._topLeftVertPosition.y, this._verts[i].position.y);
|
||||||
|
max.x = Math.max(max.x, this._verts[i].position.x);
|
||||||
|
max.y = Math.max(max.y, this._verts[i].position.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._width = max.x - this._topLeftVertPosition.x;
|
||||||
|
this._height = max.y - this._topLeftVertPosition.y;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VertexPosition{
|
||||||
|
public position: Vector2;
|
||||||
|
|
||||||
|
constructor(position: Vector2){
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
source/src/ECS/Components/PolygonMesh.ts
Normal file
12
source/src/ECS/Components/PolygonMesh.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class PolygonMesh extends Mesh {
|
||||||
|
constructor(points: Vector2[], arePointsCCW: boolean = true){
|
||||||
|
super();
|
||||||
|
|
||||||
|
let triangulator = new Triangulator();
|
||||||
|
triangulator.triangulate(points, arePointsCCW);
|
||||||
|
|
||||||
|
this.setVertPosition(points);
|
||||||
|
this.setTriangles(triangulator.triangleIndices);
|
||||||
|
this.recalculateBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
111
source/src/Utils/Triangulator.ts
Normal file
111
source/src/Utils/Triangulator.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* 三角剖分
|
||||||
|
*/
|
||||||
|
class Triangulator {
|
||||||
|
/**
|
||||||
|
* 最后一次三角调用中使用的点列表的三角形列表项的索引
|
||||||
|
*/
|
||||||
|
public triangleIndices: number[] = [];
|
||||||
|
|
||||||
|
private _triPrev: number[] = new Array<number>(12);
|
||||||
|
private _triNext: number[] = new Array<number>(12);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算一个三角形列表,该列表完全覆盖给定点集所包含的区域。如果点不是CCW,则将arePointsCCW参数传递为false
|
||||||
|
* @param points 定义封闭路径的点列表
|
||||||
|
* @param arePointsCCW
|
||||||
|
*/
|
||||||
|
public triangulate(points: Vector2[], arePointsCCW: boolean = true){
|
||||||
|
let count = points.length;
|
||||||
|
|
||||||
|
// 设置前一个链接和下一个链接
|
||||||
|
this.initialize(count);
|
||||||
|
|
||||||
|
// 非三角的多边形断路器
|
||||||
|
let iterations = 0;
|
||||||
|
|
||||||
|
// 从0开始
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
// 继续移除所有的三角形,直到只剩下一个三角形
|
||||||
|
while (count > 3 && iterations < 500){
|
||||||
|
iterations ++;
|
||||||
|
|
||||||
|
let isEar = true;
|
||||||
|
let a = points[this._triPrev[index]];
|
||||||
|
let b = points[index];
|
||||||
|
let c = points[this._triNext[index]];
|
||||||
|
|
||||||
|
if (Vector2Ext.isTriangleCCW(a, b, c)){
|
||||||
|
let k = this._triNext[this._triNext[index]];
|
||||||
|
do {
|
||||||
|
if (Triangulator.testPointTriangle(points[k], a, b, c)){
|
||||||
|
isEar = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = this._triNext[k];
|
||||||
|
} while (k != this._triPrev[index]);
|
||||||
|
}else{
|
||||||
|
isEar = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEar){
|
||||||
|
this.triangleIndices.push(this._triPrev[index]);
|
||||||
|
this.triangleIndices.push(index);
|
||||||
|
this.triangleIndices.push(this._triNext[index]);
|
||||||
|
|
||||||
|
// 删除vert通过重定向相邻vert的上一个和下一个链接,从而减少vertext计数
|
||||||
|
this._triNext[this._triPrev[index]] = this._triNext[index];
|
||||||
|
this._triPrev[this._triNext[index]] = this._triPrev[index];
|
||||||
|
count --;
|
||||||
|
|
||||||
|
// 接下来访问前一个vert
|
||||||
|
index = this._triPrev[index];
|
||||||
|
}else{
|
||||||
|
index = this._triNext[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.triangleIndices.push(this._triPrev[index]);
|
||||||
|
this.triangleIndices.push(index);
|
||||||
|
this.triangleIndices.push(this._triNext[index]);
|
||||||
|
|
||||||
|
if (!arePointsCCW)
|
||||||
|
this.triangleIndices.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initialize(count: number){
|
||||||
|
this.triangleIndices.length = 0;
|
||||||
|
|
||||||
|
if (this._triNext.length < count){
|
||||||
|
this._triNext.reverse();
|
||||||
|
this._triNext = new Array<number>(Math.max(this._triNext.length * 2, count));
|
||||||
|
}
|
||||||
|
if (this._triPrev.length < count){
|
||||||
|
this._triPrev.reverse();
|
||||||
|
this._triPrev = new Array<number>(Math.max(this._triPrev.length * 2, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < count;i ++){
|
||||||
|
this._triPrev[i] = i - 1;
|
||||||
|
this._triNext[i] = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._triPrev[0] = count - 1;
|
||||||
|
this._triNext[count - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static testPointTriangle(point: Vector2, a: Vector2, b: Vector2, c: Vector2): boolean{
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, a), Vector2.subtract(b, a)) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, b), Vector2.subtract(c, b)) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Vector2Ext.cross(Vector2.subtract(point, c), Vector2.subtract(a, c)) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
source/src/Utils/Vector2Ext.ts
Normal file
20
source/src/Utils/Vector2Ext.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
class Vector2Ext {
|
||||||
|
/**
|
||||||
|
* 检查三角形是CCW还是CW
|
||||||
|
* @param a
|
||||||
|
* @param center
|
||||||
|
* @param c
|
||||||
|
*/
|
||||||
|
public static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2){
|
||||||
|
return this.cross(Vector2.subtract(center, a), Vector2.subtract(c, center)) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算二维伪叉乘点(Perp(u), v)
|
||||||
|
* @param u
|
||||||
|
* @param v
|
||||||
|
*/
|
||||||
|
public static cross(u: Vector2, v: Vector2){
|
||||||
|
return u.y * v.x - u.x * v.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user