mirror of
https://github.com/tengge1/ShadowEditor.git
synced 2026-01-25 15:08:11 +00:00
390 lines
8.9 KiB
C#
390 lines
8.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace THREE
|
|
{
|
|
/// <summary>
|
|
/// @author bhouston / http://clara.io
|
|
/// @author mrdoob / http://mrdoob.com/
|
|
/// </summary>
|
|
public class Triangle
|
|
{
|
|
function Triangle(a, b, c )
|
|
{
|
|
|
|
this.a = (a !== undefined) ? a : new Vector3();
|
|
this.b = (b !== undefined) ? b : new Vector3();
|
|
this.c = (c !== undefined) ? c : new Vector3();
|
|
|
|
}
|
|
|
|
getNormal: function()
|
|
{
|
|
|
|
var v0 = new Vector3();
|
|
|
|
return function getNormal(a, b, c, target) {
|
|
|
|
if (target === undefined)
|
|
{
|
|
|
|
console.warn('THREE.Triangle: .getNormal() target is now required');
|
|
target = new Vector3();
|
|
|
|
}
|
|
|
|
target.subVectors(c, b);
|
|
v0.subVectors(a, b);
|
|
target.cross(v0);
|
|
|
|
var targetLengthSq = target.lengthSq();
|
|
if (targetLengthSq > 0)
|
|
{
|
|
|
|
return target.multiplyScalar(1 / Math.sqrt(targetLengthSq));
|
|
|
|
}
|
|
|
|
return target.set(0, 0, 0);
|
|
|
|
};
|
|
|
|
}
|
|
(),
|
|
|
|
// static/instance method to calculate barycentric coordinates
|
|
// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
|
|
getBarycoord: function()
|
|
{
|
|
|
|
var v0 = new Vector3();
|
|
var v1 = new Vector3();
|
|
var v2 = new Vector3();
|
|
|
|
return function getBarycoord(point, a, b, c, target) {
|
|
|
|
v0.subVectors(c, a);
|
|
v1.subVectors(b, a);
|
|
v2.subVectors(point, a);
|
|
|
|
var dot00 = v0.dot(v0);
|
|
var dot01 = v0.dot(v1);
|
|
var dot02 = v0.dot(v2);
|
|
var dot11 = v1.dot(v1);
|
|
var dot12 = v1.dot(v2);
|
|
|
|
var denom = (dot00 * dot11 - dot01 * dot01);
|
|
|
|
if (target === undefined)
|
|
{
|
|
|
|
console.warn('THREE.Triangle: .getBarycoord() target is now required');
|
|
target = new Vector3();
|
|
|
|
}
|
|
|
|
// collinear or singular triangle
|
|
if (denom === 0)
|
|
{
|
|
|
|
// arbitrary location outside of triangle?
|
|
// not sure if this is the best idea, maybe should be returning undefined
|
|
return target.set(-2, -1, -1);
|
|
|
|
}
|
|
|
|
var invDenom = 1 / denom;
|
|
var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
|
var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
|
|
|
// barycentric coordinates must always sum to 1
|
|
return target.set(1 - u - v, v, u);
|
|
|
|
};
|
|
|
|
}
|
|
(),
|
|
|
|
containsPoint: function()
|
|
{
|
|
|
|
var v1 = new Vector3();
|
|
|
|
return function containsPoint(point, a, b, c) {
|
|
|
|
Triangle.getBarycoord(point, a, b, c, v1);
|
|
|
|
return (v1.x >= 0) && (v1.y >= 0) && ((v1.x + v1.y) <= 1);
|
|
|
|
};
|
|
|
|
}
|
|
(),
|
|
|
|
getUV: function()
|
|
{
|
|
|
|
var barycoord = new Vector3();
|
|
|
|
return function getUV(point, p1, p2, p3, uv1, uv2, uv3, target) {
|
|
|
|
this.getBarycoord(point, p1, p2, p3, barycoord);
|
|
|
|
target.set(0, 0);
|
|
target.addScaledVector(uv1, barycoord.x);
|
|
target.addScaledVector(uv2, barycoord.y);
|
|
target.addScaledVector(uv3, barycoord.z);
|
|
|
|
return target;
|
|
|
|
};
|
|
|
|
}
|
|
()
|
|
|
|
} );
|
|
|
|
Object.assign(Triangle.prototype, {
|
|
|
|
set: function(a, b, c )
|
|
{
|
|
|
|
this.a.copy(a);
|
|
this.b.copy(b);
|
|
this.c.copy(c);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromPointsAndIndices: function(points, i0, i1, i2 )
|
|
{
|
|
|
|
this.a.copy(points[i0]);
|
|
this.b.copy(points[i1]);
|
|
this.c.copy(points[i2]);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clone: function()
|
|
{
|
|
|
|
return new this.constructor().copy(this);
|
|
|
|
},
|
|
|
|
copy: function(triangle )
|
|
{
|
|
|
|
this.a.copy(triangle.a);
|
|
this.b.copy(triangle.b);
|
|
this.c.copy(triangle.c);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getArea: function()
|
|
{
|
|
|
|
var v0 = new Vector3();
|
|
var v1 = new Vector3();
|
|
|
|
return function getArea() {
|
|
|
|
v0.subVectors(this.c, this.b);
|
|
v1.subVectors(this.a, this.b);
|
|
|
|
return v0.cross(v1).length() * 0.5;
|
|
|
|
};
|
|
|
|
}
|
|
(),
|
|
|
|
getMidpoint: function(target )
|
|
{
|
|
|
|
if (target === undefined)
|
|
{
|
|
|
|
console.warn('THREE.Triangle: .getMidpoint() target is now required');
|
|
target = new Vector3();
|
|
|
|
}
|
|
|
|
return target.addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3);
|
|
|
|
},
|
|
|
|
getNormal: function(target )
|
|
{
|
|
|
|
return Triangle.getNormal(this.a, this.b, this.c, target);
|
|
|
|
},
|
|
|
|
getPlane: function(target )
|
|
{
|
|
|
|
if (target === undefined)
|
|
{
|
|
|
|
console.warn('THREE.Triangle: .getPlane() target is now required');
|
|
target = new Vector3();
|
|
|
|
}
|
|
|
|
return target.setFromCoplanarPoints(this.a, this.b, this.c);
|
|
|
|
},
|
|
|
|
getBarycoord: function(point, target )
|
|
{
|
|
|
|
return Triangle.getBarycoord(point, this.a, this.b, this.c, target);
|
|
|
|
},
|
|
|
|
containsPoint: function(point )
|
|
{
|
|
|
|
return Triangle.containsPoint(point, this.a, this.b, this.c);
|
|
|
|
},
|
|
|
|
getUV: function(point, uv1, uv2, uv3, result )
|
|
{
|
|
|
|
return Triangle.getUV(point, this.a, this.b, this.c, uv1, uv2, uv3, result);
|
|
|
|
},
|
|
|
|
intersectsBox: function(box )
|
|
{
|
|
|
|
return box.intersectsTriangle(this);
|
|
|
|
},
|
|
|
|
closestPointToPoint: function()
|
|
{
|
|
|
|
var vab = new Vector3();
|
|
var vac = new Vector3();
|
|
var vbc = new Vector3();
|
|
var vap = new Vector3();
|
|
var vbp = new Vector3();
|
|
var vcp = new Vector3();
|
|
|
|
return function closestPointToPoint(p, target) {
|
|
|
|
if (target === undefined)
|
|
{
|
|
|
|
console.warn('THREE.Triangle: .closestPointToPoint() target is now required');
|
|
target = new Vector3();
|
|
|
|
}
|
|
|
|
var a = this.a, b = this.b, c = this.c;
|
|
var v, w;
|
|
|
|
// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
|
|
// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
|
|
// under the accompanying license; see chapter 5.1.5 for detailed explanation.
|
|
// basically, we're distinguishing which of the voronoi regions of the triangle
|
|
// the point lies in with the minimum amount of redundant computation.
|
|
|
|
vab.subVectors(b, a);
|
|
vac.subVectors(c, a);
|
|
vap.subVectors(p, a);
|
|
var d1 = vab.dot(vap);
|
|
var d2 = vac.dot(vap);
|
|
if (d1 <= 0 && d2 <= 0)
|
|
{
|
|
|
|
// vertex region of A; barycentric coords (1, 0, 0)
|
|
return target.copy(a);
|
|
|
|
}
|
|
|
|
vbp.subVectors(p, b);
|
|
var d3 = vab.dot(vbp);
|
|
var d4 = vac.dot(vbp);
|
|
if (d3 >= 0 && d4 <= d3)
|
|
{
|
|
|
|
// vertex region of B; barycentric coords (0, 1, 0)
|
|
return target.copy(b);
|
|
|
|
}
|
|
|
|
var vc = d1 * d4 - d3 * d2;
|
|
if (vc <= 0 && d1 >= 0 && d3 <= 0)
|
|
{
|
|
|
|
v = d1 / (d1 - d3);
|
|
// edge region of AB; barycentric coords (1-v, v, 0)
|
|
return target.copy(a).addScaledVector(vab, v);
|
|
|
|
}
|
|
|
|
vcp.subVectors(p, c);
|
|
var d5 = vab.dot(vcp);
|
|
var d6 = vac.dot(vcp);
|
|
if (d6 >= 0 && d5 <= d6)
|
|
{
|
|
|
|
// vertex region of C; barycentric coords (0, 0, 1)
|
|
return target.copy(c);
|
|
|
|
}
|
|
|
|
var vb = d5 * d2 - d1 * d6;
|
|
if (vb <= 0 && d2 >= 0 && d6 <= 0)
|
|
{
|
|
|
|
w = d2 / (d2 - d6);
|
|
// edge region of AC; barycentric coords (1-w, 0, w)
|
|
return target.copy(a).addScaledVector(vac, w);
|
|
|
|
}
|
|
|
|
var va = d3 * d6 - d5 * d4;
|
|
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)
|
|
{
|
|
|
|
vbc.subVectors(c, b);
|
|
w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
|
// edge region of BC; barycentric coords (0, 1-w, w)
|
|
return target.copy(b).addScaledVector(vbc, w); // edge region of BC
|
|
|
|
}
|
|
|
|
// face region
|
|
var denom = 1 / (va + vb + vc);
|
|
// u = va * denom
|
|
v = vb * denom;
|
|
w = vc * denom;
|
|
return target.copy(a).addScaledVector(vab, v).addScaledVector(vac, w);
|
|
|
|
};
|
|
|
|
}
|
|
(),
|
|
|
|
equals: function(triangle )
|
|
{
|
|
|
|
return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c);
|
|
|
|
}
|
|
}
|
|
}
|