add some extra assets FX and SFX
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EzySlice {
|
||||
|
||||
/**
|
||||
* A Basic Structure which contains intersection information
|
||||
* for Plane->Triangle Intersection Tests
|
||||
* TO-DO -> This structure can be optimized to hold less data
|
||||
* via an optional indices array. Could lead for a faster
|
||||
* intersection test aswell.
|
||||
*/
|
||||
public sealed class IntersectionResult {
|
||||
|
||||
// general tag to check if this structure is valid
|
||||
private bool is_success;
|
||||
|
||||
// our intersection points/triangles
|
||||
private readonly Triangle[] upper_hull;
|
||||
private readonly Triangle[] lower_hull;
|
||||
private readonly Vector3[] intersection_pt;
|
||||
|
||||
// our counters. We use raw arrays for performance reasons
|
||||
private int upper_hull_count;
|
||||
private int lower_hull_count;
|
||||
private int intersection_pt_count;
|
||||
|
||||
public IntersectionResult() {
|
||||
this.is_success = false;
|
||||
|
||||
this.upper_hull = new Triangle[2];
|
||||
this.lower_hull = new Triangle[2];
|
||||
this.intersection_pt = new Vector3[2];
|
||||
|
||||
this.upper_hull_count = 0;
|
||||
this.lower_hull_count = 0;
|
||||
this.intersection_pt_count = 0;
|
||||
}
|
||||
|
||||
public Triangle[] upperHull {
|
||||
get { return upper_hull; }
|
||||
}
|
||||
|
||||
public Triangle[] lowerHull {
|
||||
get { return lower_hull; }
|
||||
}
|
||||
|
||||
public Vector3[] intersectionPoints {
|
||||
get { return intersection_pt; }
|
||||
}
|
||||
|
||||
public int upperHullCount {
|
||||
get { return upper_hull_count; }
|
||||
}
|
||||
|
||||
public int lowerHullCount {
|
||||
get { return lower_hull_count; }
|
||||
}
|
||||
|
||||
public int intersectionPointCount {
|
||||
get { return intersection_pt_count; }
|
||||
}
|
||||
|
||||
public bool isValid {
|
||||
get { return is_success; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the intersector, adds a new triangle to the
|
||||
* upper hull section
|
||||
*/
|
||||
public IntersectionResult AddUpperHull(Triangle tri) {
|
||||
upper_hull[upper_hull_count++] = tri;
|
||||
|
||||
is_success = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the intersector, adds a new triangle to the
|
||||
* lower gull section
|
||||
*/
|
||||
public IntersectionResult AddLowerHull(Triangle tri) {
|
||||
lower_hull[lower_hull_count++] = tri;
|
||||
|
||||
is_success = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the intersector, adds a new intersection point
|
||||
* which is shared by both upper->lower hulls
|
||||
*/
|
||||
public void AddIntersectionPoint(Vector3 pt) {
|
||||
intersection_pt[intersection_pt_count++] = pt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the current state of this object
|
||||
*/
|
||||
public void Clear() {
|
||||
is_success = false;
|
||||
upper_hull_count = 0;
|
||||
lower_hull_count = 0;
|
||||
intersection_pt_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Editor only DEBUG functionality. This should not be compiled in the final
|
||||
* Version.
|
||||
*/
|
||||
public void OnDebugDraw() {
|
||||
OnDebugDraw(Color.white);
|
||||
}
|
||||
|
||||
public void OnDebugDraw(Color drawColor) {
|
||||
#if UNITY_EDITOR
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
Color prevColor = Gizmos.color;
|
||||
|
||||
Gizmos.color = drawColor;
|
||||
|
||||
// draw the intersection points
|
||||
for (int i = 0; i < intersectionPointCount; i++) {
|
||||
Gizmos.DrawSphere(intersectionPoints[i], 0.1f);
|
||||
}
|
||||
|
||||
// draw the upper hull in RED
|
||||
for (int i = 0; i < upperHullCount; i++) {
|
||||
upperHull[i].OnDebugDraw(Color.red);
|
||||
}
|
||||
|
||||
// draw the lower hull in BLUE
|
||||
for (int i = 0; i < lowerHullCount; i++) {
|
||||
lowerHull[i].OnDebugDraw(Color.blue);
|
||||
}
|
||||
|
||||
Gizmos.color = prevColor;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6348dbaec6c064505808c4ee233b5a0e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 40995
|
||||
packageName: Game Kit Controller - Shooter Melee Adventure FPS TPS Creator 3D +
|
||||
2.5D
|
||||
packageVersion: 3.77h
|
||||
assetPath: Assets/Game Kit Controller/Integrations/EzySlice/Framework/IntersectionResult.cs
|
||||
uploadId: 889948
|
||||
@@ -0,0 +1,487 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EzySlice {
|
||||
/**
|
||||
* Contains static functionality to perform geometric intersection tests.
|
||||
*/
|
||||
public sealed class Intersector {
|
||||
|
||||
/**
|
||||
* Perform an intersection between Plane and Line, storing intersection point
|
||||
* in reference q. Function returns true if intersection has been found or
|
||||
* false otherwise.
|
||||
*/
|
||||
public static bool Intersect(Plane pl, Line ln, out Vector3 q) {
|
||||
return Intersector.Intersect(pl, ln.positionA, ln.positionB, out q);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an intersection between Plane and Line made up of points a and b. Intersection
|
||||
* point will be stored in reference q. Function returns true if intersection has been
|
||||
* found or false otherwise.
|
||||
*/
|
||||
public static bool Intersect(Plane pl, Vector3 a, Vector3 b, out Vector3 q) {
|
||||
Vector3 normal = pl.normal;
|
||||
Vector3 ab = b - a;
|
||||
|
||||
float t = (pl.dist - Vector3.Dot(normal, a)) / Vector3.Dot(normal, ab);
|
||||
|
||||
// need to be careful and compensate for floating errors
|
||||
if (t >= -float.Epsilon && t <= (1 + float.Epsilon)) {
|
||||
q = a + t * ab;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
q = Vector3.zero;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support functionality
|
||||
*/
|
||||
public static float TriArea2D(float x1, float y1, float x2, float y2, float x3, float y3) {
|
||||
return (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an intersection between Plane and Triangle. This is a comprehensive function
|
||||
* which alwo builds a HULL Hirearchy useful for decimation projects. This obviously
|
||||
* comes at the cost of more complex code and runtime checks, but the returned results
|
||||
* are much more flexible.
|
||||
* Results will be filled into the IntersectionResult reference. Check result.isValid()
|
||||
* for the final results.
|
||||
*/
|
||||
public static void Intersect(Plane pl, Triangle tri, IntersectionResult result) {
|
||||
// clear the previous results from the IntersectionResult
|
||||
result.Clear();
|
||||
|
||||
// grab local variables for easier access
|
||||
Vector3 a = tri.positionA;
|
||||
Vector3 b = tri.positionB;
|
||||
Vector3 c = tri.positionC;
|
||||
|
||||
// check to see which side of the plane the points all
|
||||
// lay in. SideOf operation is a simple dot product and some comparison
|
||||
// operations, so these are a very quick checks
|
||||
SideOfPlane sa = pl.SideOf(a);
|
||||
SideOfPlane sb = pl.SideOf(b);
|
||||
SideOfPlane sc = pl.SideOf(c);
|
||||
|
||||
// we cannot intersect if the triangle points all fall on the same side
|
||||
// of the plane. This is an easy early out test as no intersections are possible.
|
||||
if (sa == sb && sb == sc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// detect cases where two points lay straight on the plane, meaning
|
||||
// that the plane is actually parralel with one of the edges of the triangle
|
||||
else if ((sa == SideOfPlane.ON && sa == sb) ||
|
||||
(sa == SideOfPlane.ON && sa == sc) ||
|
||||
(sb == SideOfPlane.ON && sb == sc))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// keep in mind that intersection points are shared by both
|
||||
// the upper HULL and lower HULL hence they lie perfectly
|
||||
// on the plane that cut them
|
||||
Vector3 qa;
|
||||
Vector3 qb;
|
||||
|
||||
// check the cases where the points of the triangle actually lie on the plane itself
|
||||
// in these cases, there is only going to be 2 triangles, one for the upper HULL and
|
||||
// the other on the lower HULL
|
||||
// we just need to figure out which points to accept into the upper or lower hulls.
|
||||
if (sa == SideOfPlane.ON) {
|
||||
// if the point a is on the plane, test line b-c
|
||||
if (Intersector.Intersect(pl, b, c, out qa)) {
|
||||
// line b-c intersected, construct out triangles and return approprietly
|
||||
result.AddIntersectionPoint(qa);
|
||||
result.AddIntersectionPoint(a);
|
||||
|
||||
// our two generated triangles, we need to figure out which
|
||||
// triangle goes into the UPPER hull and which goes into the LOWER hull
|
||||
Triangle ta = new Triangle(a, b, qa);
|
||||
Triangle tb = new Triangle(a, qa, c);
|
||||
|
||||
// generate UV coordinates if there is any
|
||||
if (tri.hasUV) {
|
||||
// the computed UV coordinate if the intersection point
|
||||
Vector2 pq = tri.GenerateUV(qa);
|
||||
Vector2 pa = tri.uvA;
|
||||
Vector2 pb = tri.uvB;
|
||||
Vector2 pc = tri.uvC;
|
||||
|
||||
ta.SetUV(pa, pb, pq);
|
||||
tb.SetUV(pa, pq, pc);
|
||||
}
|
||||
|
||||
// generate Normal coordinates if there is any
|
||||
if (tri.hasNormal) {
|
||||
// the computed Normal coordinate if the intersection point
|
||||
Vector3 pq = tri.GenerateNormal(qa);
|
||||
Vector3 pa = tri.normalA;
|
||||
Vector3 pb = tri.normalB;
|
||||
Vector3 pc = tri.normalC;
|
||||
|
||||
ta.SetNormal(pa, pb, pq);
|
||||
tb.SetNormal(pa, pq, pc);
|
||||
}
|
||||
|
||||
// generate Tangent coordinates if there is any
|
||||
if (tri.hasTangent) {
|
||||
// the computed Tangent coordinate if the intersection point
|
||||
Vector4 pq = tri.GenerateTangent(qa);
|
||||
Vector4 pa = tri.tangentA;
|
||||
Vector4 pb = tri.tangentB;
|
||||
Vector4 pc = tri.tangentC;
|
||||
|
||||
ta.SetTangent(pa, pb, pq);
|
||||
tb.SetTangent(pa, pq, pc);
|
||||
}
|
||||
|
||||
// b point lies on the upside of the plane
|
||||
if (sb == SideOfPlane.UP) {
|
||||
result.AddUpperHull(ta).AddLowerHull(tb);
|
||||
}
|
||||
|
||||
// b point lies on the downside of the plane
|
||||
else if (sb == SideOfPlane.DOWN) {
|
||||
result.AddUpperHull(tb).AddLowerHull(ta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test the case where the b point lies on the plane itself
|
||||
else if (sb == SideOfPlane.ON) {
|
||||
// if the point b is on the plane, test line a-c
|
||||
if (Intersector.Intersect(pl, a, c, out qa)) {
|
||||
// line a-c intersected, construct out triangles and return approprietly
|
||||
result.AddIntersectionPoint(qa);
|
||||
result.AddIntersectionPoint(b);
|
||||
|
||||
// our two generated triangles, we need to figure out which
|
||||
// triangle goes into the UPPER hull and which goes into the LOWER hull
|
||||
Triangle ta = new Triangle(a, b, qa);
|
||||
Triangle tb = new Triangle(qa, b, c);
|
||||
|
||||
// generate UV coordinates if there is any
|
||||
if (tri.hasUV) {
|
||||
// the computed UV coordinate if the intersection point
|
||||
Vector2 pq = tri.GenerateUV(qa);
|
||||
Vector2 pa = tri.uvA;
|
||||
Vector2 pb = tri.uvB;
|
||||
Vector2 pc = tri.uvC;
|
||||
|
||||
ta.SetUV(pa, pb, pq);
|
||||
tb.SetUV(pq, pb, pc);
|
||||
}
|
||||
|
||||
// generate Normal coordinates if there is any
|
||||
if (tri.hasNormal) {
|
||||
// the computed Normal coordinate if the intersection point
|
||||
Vector3 pq = tri.GenerateNormal(qa);
|
||||
Vector3 pa = tri.normalA;
|
||||
Vector3 pb = tri.normalB;
|
||||
Vector3 pc = tri.normalC;
|
||||
|
||||
ta.SetNormal(pa, pb, pq);
|
||||
tb.SetNormal(pq, pb, pc);
|
||||
}
|
||||
|
||||
// generate Tangent coordinates if there is any
|
||||
if (tri.hasTangent) {
|
||||
// the computed Tangent coordinate if the intersection point
|
||||
Vector4 pq = tri.GenerateTangent(qa);
|
||||
Vector4 pa = tri.tangentA;
|
||||
Vector4 pb = tri.tangentB;
|
||||
Vector4 pc = tri.tangentC;
|
||||
|
||||
ta.SetTangent(pa, pb, pq);
|
||||
tb.SetTangent(pq, pb, pc);
|
||||
}
|
||||
|
||||
// a point lies on the upside of the plane
|
||||
if (sa == SideOfPlane.UP) {
|
||||
result.AddUpperHull(ta).AddLowerHull(tb);
|
||||
}
|
||||
|
||||
// a point lies on the downside of the plane
|
||||
else if (sa == SideOfPlane.DOWN) {
|
||||
result.AddUpperHull(tb).AddLowerHull(ta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test the case where the c point lies on the plane itself
|
||||
else if (sc == SideOfPlane.ON) {
|
||||
// if the point c is on the plane, test line a-b
|
||||
if (Intersector.Intersect(pl, a, b, out qa)) {
|
||||
// line a-c intersected, construct out triangles and return approprietly
|
||||
result.AddIntersectionPoint(qa);
|
||||
result.AddIntersectionPoint(c);
|
||||
|
||||
// our two generated triangles, we need to figure out which
|
||||
// triangle goes into the UPPER hull and which goes into the LOWER hull
|
||||
Triangle ta = new Triangle(a, qa, c);
|
||||
Triangle tb = new Triangle(qa, b, c);
|
||||
|
||||
// generate UV coordinates if there is any
|
||||
if (tri.hasUV) {
|
||||
// the computed UV coordinate if the intersection point
|
||||
Vector2 pq = tri.GenerateUV(qa);
|
||||
Vector2 pa = tri.uvA;
|
||||
Vector2 pb = tri.uvB;
|
||||
Vector2 pc = tri.uvC;
|
||||
|
||||
ta.SetUV(pa, pq, pc);
|
||||
tb.SetUV(pq, pb, pc);
|
||||
}
|
||||
|
||||
// generate Normal coordinates if there is any
|
||||
if (tri.hasNormal) {
|
||||
// the computed Normal coordinate if the intersection point
|
||||
Vector3 pq = tri.GenerateNormal(qa);
|
||||
Vector3 pa = tri.normalA;
|
||||
Vector3 pb = tri.normalB;
|
||||
Vector3 pc = tri.normalC;
|
||||
|
||||
ta.SetNormal(pa, pq, pc);
|
||||
tb.SetNormal(pq, pb, pc);
|
||||
}
|
||||
|
||||
// generate Tangent coordinates if there is any
|
||||
if (tri.hasTangent) {
|
||||
// the computed Tangent coordinate if the intersection point
|
||||
Vector4 pq = tri.GenerateTangent(qa);
|
||||
Vector4 pa = tri.tangentA;
|
||||
Vector4 pb = tri.tangentB;
|
||||
Vector4 pc = tri.tangentC;
|
||||
|
||||
ta.SetTangent(pa, pq, pc);
|
||||
tb.SetTangent(pq, pb, pc);
|
||||
}
|
||||
|
||||
// a point lies on the upside of the plane
|
||||
if (sa == SideOfPlane.UP) {
|
||||
result.AddUpperHull(ta).AddLowerHull(tb);
|
||||
}
|
||||
|
||||
// a point lies on the downside of the plane
|
||||
else if (sa == SideOfPlane.DOWN) {
|
||||
result.AddUpperHull(tb).AddLowerHull(ta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// at this point, all edge cases have been tested and failed, we need to perform
|
||||
// full intersection tests against the lines. From this point onwards we will generate
|
||||
// 3 triangles
|
||||
else if (sa != sb && Intersector.Intersect(pl, a, b, out qa)) {
|
||||
// intersection found against a - b
|
||||
result.AddIntersectionPoint(qa);
|
||||
|
||||
// since intersection was found against a - b, we need to check which other
|
||||
// lines to check (we only need to check one more line) for intersection.
|
||||
// the line we check against will be the line against the point which lies on
|
||||
// the other side of the plane.
|
||||
if (sa == sc) {
|
||||
// we likely have an intersection against line b-c which will complete this loop
|
||||
if (Intersector.Intersect(pl, b, c, out qb)) {
|
||||
result.AddIntersectionPoint(qb);
|
||||
|
||||
// our three generated triangles. Two of these triangles will end
|
||||
// up on either the UPPER or LOWER hulls.
|
||||
Triangle ta = new Triangle(qa, b, qb);
|
||||
Triangle tb = new Triangle(a, qa, qb);
|
||||
Triangle tc = new Triangle(a, qb, c);
|
||||
|
||||
// generate UV coordinates if there is any
|
||||
if (tri.hasUV) {
|
||||
// the computed UV coordinate if the intersection point
|
||||
Vector2 pqa = tri.GenerateUV(qa);
|
||||
Vector2 pqb = tri.GenerateUV(qb);
|
||||
Vector2 pa = tri.uvA;
|
||||
Vector2 pb = tri.uvB;
|
||||
Vector2 pc = tri.uvC;
|
||||
|
||||
ta.SetUV(pqa, pb, pqb);
|
||||
tb.SetUV(pa, pqa, pqb);
|
||||
tc.SetUV(pa, pqb, pc);
|
||||
}
|
||||
|
||||
// generate Normal coordinates if there is any
|
||||
if (tri.hasNormal) {
|
||||
// the computed Normal coordinate if the intersection point
|
||||
Vector3 pqa = tri.GenerateNormal(qa);
|
||||
Vector3 pqb = tri.GenerateNormal(qb);
|
||||
Vector3 pa = tri.normalA;
|
||||
Vector3 pb = tri.normalB;
|
||||
Vector3 pc = tri.normalC;
|
||||
|
||||
ta.SetNormal(pqa, pb, pqb);
|
||||
tb.SetNormal(pa, pqa, pqb);
|
||||
tc.SetNormal(pa, pqb, pc);
|
||||
}
|
||||
|
||||
// generate Tangent coordinates if there is any
|
||||
if (tri.hasTangent) {
|
||||
// the computed Tangent coordinate if the intersection point
|
||||
Vector4 pqa = tri.GenerateTangent(qa);
|
||||
Vector4 pqb = tri.GenerateTangent(qb);
|
||||
Vector4 pa = tri.tangentA;
|
||||
Vector4 pb = tri.tangentB;
|
||||
Vector4 pc = tri.tangentC;
|
||||
|
||||
ta.SetTangent(pqa, pb, pqb);
|
||||
tb.SetTangent(pa, pqa, pqb);
|
||||
tc.SetTangent(pa, pqb, pc);
|
||||
}
|
||||
|
||||
if (sa == SideOfPlane.UP) {
|
||||
result.AddUpperHull(tb).AddUpperHull(tc).AddLowerHull(ta);
|
||||
}
|
||||
else {
|
||||
result.AddLowerHull(tb).AddLowerHull(tc).AddUpperHull(ta);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// in this scenario, the point a is a "lone" point which lies in either upper
|
||||
// or lower HULL. We need to perform another intersection to find the last point
|
||||
if (Intersector.Intersect(pl, a, c, out qb)) {
|
||||
result.AddIntersectionPoint(qb);
|
||||
|
||||
// our three generated triangles. Two of these triangles will end
|
||||
// up on either the UPPER or LOWER hulls.
|
||||
Triangle ta = new Triangle(a, qa, qb);
|
||||
Triangle tb = new Triangle(qa, b, c);
|
||||
Triangle tc = new Triangle(qb, qa, c);
|
||||
|
||||
// generate UV coordinates if there is any
|
||||
if (tri.hasUV) {
|
||||
// the computed UV coordinate if the intersection point
|
||||
Vector2 pqa = tri.GenerateUV(qa);
|
||||
Vector2 pqb = tri.GenerateUV(qb);
|
||||
Vector2 pa = tri.uvA;
|
||||
Vector2 pb = tri.uvB;
|
||||
Vector2 pc = tri.uvC;
|
||||
|
||||
ta.SetUV(pa, pqa, pqb);
|
||||
tb.SetUV(pqa, pb, pc);
|
||||
tc.SetUV(pqb, pqa, pc);
|
||||
}
|
||||
|
||||
// generate Normal coordinates if there is any
|
||||
if (tri.hasNormal) {
|
||||
// the computed Normal coordinate if the intersection point
|
||||
Vector3 pqa = tri.GenerateNormal(qa);
|
||||
Vector3 pqb = tri.GenerateNormal(qb);
|
||||
Vector3 pa = tri.normalA;
|
||||
Vector3 pb = tri.normalB;
|
||||
Vector3 pc = tri.normalC;
|
||||
|
||||
ta.SetNormal(pa, pqa, pqb);
|
||||
tb.SetNormal(pqa, pb, pc);
|
||||
tc.SetNormal(pqb, pqa, pc);
|
||||
}
|
||||
|
||||
// generate Tangent coordinates if there is any
|
||||
if (tri.hasTangent) {
|
||||
// the computed Tangent coordinate if the intersection point
|
||||
Vector4 pqa = tri.GenerateTangent(qa);
|
||||
Vector4 pqb = tri.GenerateTangent(qb);
|
||||
Vector4 pa = tri.tangentA;
|
||||
Vector4 pb = tri.tangentB;
|
||||
Vector4 pc = tri.tangentC;
|
||||
|
||||
ta.SetTangent(pa, pqa, pqb);
|
||||
tb.SetTangent(pqa, pb, pc);
|
||||
tc.SetTangent(pqb, pqa, pc);
|
||||
}
|
||||
|
||||
if (sa == SideOfPlane.UP) {
|
||||
result.AddUpperHull(ta).AddLowerHull(tb).AddLowerHull(tc);
|
||||
}
|
||||
else {
|
||||
result.AddLowerHull(ta).AddUpperHull(tb).AddUpperHull(tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if line a-b did not intersect (or the lie on the same side of the plane)
|
||||
// this simplifies the problem a fair bit. This means we have an intersection
|
||||
// in line a-c and b-c, which we can use to build a new UPPER and LOWER hulls
|
||||
// we are expecting both of these intersection tests to pass, otherwise something
|
||||
// went wrong (float errors? missed a checked case?)
|
||||
else if (Intersector.Intersect(pl, c, a, out qa) && Intersector.Intersect(pl, c, b, out qb)) {
|
||||
// in here we know that line a-b actually lie on the same side of the plane, this will
|
||||
// simplify the rest of the logic. We also have our intersection points
|
||||
// the computed UV coordinate of the intersection point
|
||||
|
||||
result.AddIntersectionPoint(qa);
|
||||
result.AddIntersectionPoint(qb);
|
||||
|
||||
// our three generated triangles. Two of these triangles will end
|
||||
// up on either the UPPER or LOWER hulls.
|
||||
Triangle ta = new Triangle(qa, qb, c);
|
||||
Triangle tb = new Triangle(a, qb, qa);
|
||||
Triangle tc = new Triangle(a, b, qb);
|
||||
|
||||
// generate UV coordinates if there is any
|
||||
if (tri.hasUV) {
|
||||
// the computed UV coordinate if the intersection point
|
||||
Vector2 pqa = tri.GenerateUV(qa);
|
||||
Vector2 pqb = tri.GenerateUV(qb);
|
||||
Vector2 pa = tri.uvA;
|
||||
Vector2 pb = tri.uvB;
|
||||
Vector2 pc = tri.uvC;
|
||||
|
||||
ta.SetUV(pqa, pqb, pc);
|
||||
tb.SetUV(pa, pqb, pqa);
|
||||
tc.SetUV(pa, pb, pqb);
|
||||
}
|
||||
|
||||
// generate Normal coordinates if there is any
|
||||
if (tri.hasNormal) {
|
||||
// the computed Normal coordinate if the intersection point
|
||||
Vector3 pqa = tri.GenerateNormal(qa);
|
||||
Vector3 pqb = tri.GenerateNormal(qb);
|
||||
Vector3 pa = tri.normalA;
|
||||
Vector3 pb = tri.normalB;
|
||||
Vector3 pc = tri.normalC;
|
||||
|
||||
ta.SetNormal(pqa, pqb, pc);
|
||||
tb.SetNormal(pa, pqb, pqa);
|
||||
tc.SetNormal(pa, pb, pqb);
|
||||
}
|
||||
|
||||
// generate Tangent coordinates if there is any
|
||||
if (tri.hasTangent) {
|
||||
// the computed Tangent coordinate if the intersection point
|
||||
Vector4 pqa = tri.GenerateTangent(qa);
|
||||
Vector4 pqb = tri.GenerateTangent(qb);
|
||||
Vector4 pa = tri.tangentA;
|
||||
Vector4 pb = tri.tangentB;
|
||||
Vector4 pc = tri.tangentC;
|
||||
|
||||
ta.SetTangent(pqa, pqb, pc);
|
||||
tb.SetTangent(pa, pqb, pqa);
|
||||
tc.SetTangent(pa, pb, pqb);
|
||||
}
|
||||
|
||||
if (sa == SideOfPlane.UP) {
|
||||
result.AddUpperHull(tb).AddUpperHull(tc).AddLowerHull(ta);
|
||||
}
|
||||
else {
|
||||
result.AddLowerHull(tb).AddLowerHull(tc).AddUpperHull(ta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68977ed014f58453a8e1a8413810cb98
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 40995
|
||||
packageName: Game Kit Controller - Shooter Melee Adventure FPS TPS Creator 3D +
|
||||
2.5D
|
||||
packageVersion: 3.77h
|
||||
assetPath: Assets/Game Kit Controller/Integrations/EzySlice/Framework/Intersector.cs
|
||||
uploadId: 889948
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EzySlice {
|
||||
public struct Line {
|
||||
private readonly Vector3 m_pos_a;
|
||||
private readonly Vector3 m_pos_b;
|
||||
|
||||
public Line(Vector3 pta, Vector3 ptb) {
|
||||
this.m_pos_a = pta;
|
||||
this.m_pos_b = ptb;
|
||||
}
|
||||
|
||||
public float dist {
|
||||
get { return GKC_Utils.distance (this.m_pos_a, this.m_pos_b); }
|
||||
}
|
||||
|
||||
public float distSq {
|
||||
get { return (this.m_pos_a - this.m_pos_b).sqrMagnitude; }
|
||||
}
|
||||
|
||||
public Vector3 positionA {
|
||||
get { return this.m_pos_a; }
|
||||
}
|
||||
|
||||
public Vector3 positionB {
|
||||
get { return this.m_pos_b; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f79fe4ab0d9d54fc0b2878eff9a317b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 40995
|
||||
packageName: Game Kit Controller - Shooter Melee Adventure FPS TPS Creator 3D +
|
||||
2.5D
|
||||
packageVersion: 3.77h
|
||||
assetPath: Assets/Game Kit Controller/Integrations/EzySlice/Framework/Line.cs
|
||||
uploadId: 889948
|
||||
@@ -0,0 +1,142 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EzySlice
|
||||
{
|
||||
|
||||
/**
|
||||
* Quick Internal structure which checks where the point lays on the
|
||||
* Plane. UP = Upwards from the Normal, DOWN = Downwards from the Normal
|
||||
* ON = Point lays straight on the plane
|
||||
*/
|
||||
public enum SideOfPlane
|
||||
{
|
||||
UP,
|
||||
DOWN,
|
||||
ON
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a simple 3D Plane structure with a position
|
||||
* and direction which extends infinitely in its axis. This provides
|
||||
* an optimal structure for collision tests for the slicing framework.
|
||||
*/
|
||||
public struct Plane
|
||||
{
|
||||
private Vector3 m_normal;
|
||||
private float m_dist;
|
||||
|
||||
// this is for editor debugging only! do NOT try to access this
|
||||
// variable at runtime, we will be stripping it out for final
|
||||
// builds
|
||||
#if UNITY_EDITOR
|
||||
private Transform trans_ref;
|
||||
#endif
|
||||
|
||||
public Plane (Vector3 pos, Vector3 norm)
|
||||
{
|
||||
this.m_normal = norm;
|
||||
this.m_dist = Vector3.Dot (norm, pos);
|
||||
|
||||
// this is for editor debugging only!
|
||||
#if UNITY_EDITOR
|
||||
trans_ref = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
public Plane (Vector3 norm, float dot)
|
||||
{
|
||||
this.m_normal = norm;
|
||||
this.m_dist = dot;
|
||||
|
||||
// this is for editor debugging only!
|
||||
#if UNITY_EDITOR
|
||||
trans_ref = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Compute (Vector3 pos, Vector3 norm)
|
||||
{
|
||||
this.m_normal = norm;
|
||||
this.m_dist = Vector3.Dot (norm, pos);
|
||||
}
|
||||
|
||||
public void Compute (Transform trans)
|
||||
{
|
||||
Compute (trans.position, trans.up);
|
||||
|
||||
// this is for editor debugging only!
|
||||
#if UNITY_EDITOR
|
||||
trans_ref = trans;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Compute (GameObject obj)
|
||||
{
|
||||
Compute (obj.transform);
|
||||
}
|
||||
|
||||
public Vector3 normal {
|
||||
get { return this.m_normal; }
|
||||
}
|
||||
|
||||
public float dist {
|
||||
get { return this.m_dist; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks which side of the plane the point lays on.
|
||||
*/
|
||||
public SideOfPlane SideOf (Vector3 pt)
|
||||
{
|
||||
float result = Vector3.Dot (m_normal, pt) - m_dist;
|
||||
|
||||
if (result > float.Epsilon) {
|
||||
return SideOfPlane.UP;
|
||||
}
|
||||
|
||||
if (result < -float.Epsilon) {
|
||||
return SideOfPlane.DOWN;
|
||||
}
|
||||
|
||||
return SideOfPlane.ON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Editor only DEBUG functionality. This should not be compiled in the final
|
||||
* Version.
|
||||
*/
|
||||
public void OnDebugDraw ()
|
||||
{
|
||||
OnDebugDraw (Color.white);
|
||||
}
|
||||
|
||||
public void OnDebugDraw (Color drawColor)
|
||||
{
|
||||
// NOTE -> Gizmos are only supported in the editor. We will keep these function
|
||||
// signatures for consistancy however at final build, these will do nothing
|
||||
// TO/DO -> Should we throw a runtime exception if this function tried to get executed
|
||||
// at runtime?
|
||||
#if UNITY_EDITOR
|
||||
|
||||
if (trans_ref == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Color prevColor = Gizmos.color;
|
||||
Matrix4x4 prevMatrix = Gizmos.matrix;
|
||||
|
||||
// TO-DO
|
||||
Gizmos.matrix = Matrix4x4.TRS (trans_ref.position, trans_ref.rotation, trans_ref.localScale);
|
||||
Gizmos.color = drawColor;
|
||||
|
||||
Gizmos.DrawWireCube (Vector3.zero, new Vector3 (1.0f, 0.0f, 1.0f));
|
||||
|
||||
Gizmos.color = prevColor;
|
||||
Gizmos.matrix = prevMatrix;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea181f2949b1a49968de7347c70f068a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 40995
|
||||
packageName: Game Kit Controller - Shooter Melee Adventure FPS TPS Creator 3D +
|
||||
2.5D
|
||||
packageVersion: 3.77h
|
||||
assetPath: Assets/Game Kit Controller/Integrations/EzySlice/Framework/Plane.cs
|
||||
uploadId: 889948
|
||||
@@ -0,0 +1,117 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EzySlice {
|
||||
/**
|
||||
* TextureRegion defines a region of a specific texture which can be used
|
||||
* for custom UV Mapping Routines.
|
||||
*
|
||||
* TextureRegions are always stored in normalized UV Coordinate space between
|
||||
* 0.0f and 1.0f
|
||||
*/
|
||||
public struct TextureRegion {
|
||||
private readonly float pos_start_x;
|
||||
private readonly float pos_start_y;
|
||||
private readonly float pos_end_x;
|
||||
private readonly float pos_end_y;
|
||||
|
||||
public TextureRegion(float startX, float startY, float endX, float endY) {
|
||||
this.pos_start_x = startX;
|
||||
this.pos_start_y = startY;
|
||||
this.pos_end_x = endX;
|
||||
this.pos_end_y = endY;
|
||||
}
|
||||
|
||||
public float startX { get { return this.pos_start_x; } }
|
||||
public float startY { get { return this.pos_start_y; } }
|
||||
public float endX { get { return this.pos_end_x; } }
|
||||
public float endY { get { return this.pos_end_y; } }
|
||||
|
||||
public Vector2 start { get { return new Vector2(startX, startY); } }
|
||||
public Vector2 end { get { return new Vector2(endX, endY); } }
|
||||
|
||||
/**
|
||||
* Perform a mapping of a UV coordinate (computed in 0,1 space)
|
||||
* into the new coordinates defined by the provided TextureRegion
|
||||
*/
|
||||
public Vector2 Map(Vector2 uv) {
|
||||
return Map(uv.x, uv.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a mapping of a UV coordinate (computed in 0,1 space)
|
||||
* into the new coordinates defined by the provided TextureRegion
|
||||
*/
|
||||
public Vector2 Map(float x, float y) {
|
||||
float mappedX = MAP(x, 0.0f, 1.0f, pos_start_x, pos_end_x);
|
||||
float mappedY = MAP(y, 0.0f, 1.0f, pos_start_y, pos_end_y);
|
||||
|
||||
return new Vector2(mappedX, mappedY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Our mapping function to map arbitrary values into our required texture region
|
||||
*/
|
||||
private static float MAP(float x, float in_min, float in_max, float out_min, float out_max) {
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define our TextureRegion extension to easily calculate
|
||||
* from a Texture2D Object.
|
||||
*/
|
||||
public static class TextureRegionExtension {
|
||||
|
||||
// /**
|
||||
// * Helper function to quickly calculate the Texture Region from a material.
|
||||
// * This extension function will use the mainTexture component to perform the
|
||||
// * calculation.
|
||||
// *
|
||||
// * Will throw a null exception if the texture does not exist. See
|
||||
// * Texture.getTextureRegion() for function details.
|
||||
// */
|
||||
// public static TextureRegion GetTextureRegion(this Material mat,
|
||||
// int pixX,
|
||||
// int pixY,
|
||||
// int pixWidth,
|
||||
// int pixHeight)
|
||||
// {
|
||||
// return mat.mainTexture.GetTextureRegion(pixX, pixY, pixWidth, pixHeight);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Using a Texture2D, calculate and return a specific TextureRegion
|
||||
// * Coordinates are provided in pixel coordinates where 0,0 is the
|
||||
// * bottom left corner of the texture.
|
||||
// *
|
||||
// * The texture region will automatically be calculated to ensure that it
|
||||
// * will fit inside the provided texture.
|
||||
// */
|
||||
// public static TextureRegion GetTextureRegion(this Texture tex,
|
||||
// int pixX,
|
||||
// int pixY,
|
||||
// int pixWidth,
|
||||
// int pixHeight)
|
||||
// {
|
||||
// int textureWidth = tex.width;
|
||||
// int textureHeight = tex.height;
|
||||
//
|
||||
// // ensure we are not referencing out of bounds coordinates
|
||||
// // relative to our texture
|
||||
// int calcWidth = Mathf.Min(textureWidth, pixWidth);
|
||||
// int calcHeight = Mathf.Min(textureHeight, pixHeight);
|
||||
// int calcX = Mathf.Min(Mathf.Abs(pixX), textureWidth);
|
||||
// int calcY = Mathf.Min(Mathf.Abs(pixY), textureHeight);
|
||||
//
|
||||
// float startX = calcX / (float)textureWidth;
|
||||
// float startY = calcY / (float)textureHeight;
|
||||
// float endX = (calcX + calcWidth) / (float)textureWidth;
|
||||
// float endY = (calcY + calcHeight) / (float)textureHeight;
|
||||
//
|
||||
// // texture region is a struct which is allocated on the stack
|
||||
// return new TextureRegion(startX, startY, endX, endY);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e51e783641a5e49d3862ecbee26cc521
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 40995
|
||||
packageName: Game Kit Controller - Shooter Melee Adventure FPS TPS Creator 3D +
|
||||
2.5D
|
||||
packageVersion: 3.77h
|
||||
assetPath: Assets/Game Kit Controller/Integrations/EzySlice/Framework/TextureRegion.cs
|
||||
uploadId: 889948
|
||||
@@ -0,0 +1,352 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EzySlice {
|
||||
/**
|
||||
* Represents a simple 3D Triangle structure with position
|
||||
* and UV map. The UV is required if the slicer needs
|
||||
* to recalculate the new UV position for texture mapping.
|
||||
*/
|
||||
public struct Triangle {
|
||||
// the points which represent this triangle
|
||||
// these have to be set and are immutable. Cannot be
|
||||
// changed once set
|
||||
private readonly Vector3 m_pos_a;
|
||||
private readonly Vector3 m_pos_b;
|
||||
private readonly Vector3 m_pos_c;
|
||||
|
||||
// the UV coordinates of this triangle
|
||||
// these are optional and may not be set
|
||||
private bool m_uv_set;
|
||||
private Vector2 m_uv_a;
|
||||
private Vector2 m_uv_b;
|
||||
private Vector2 m_uv_c;
|
||||
|
||||
// the Normals of the Vertices
|
||||
// these are optional and may not be set
|
||||
private bool m_nor_set;
|
||||
private Vector3 m_nor_a;
|
||||
private Vector3 m_nor_b;
|
||||
private Vector3 m_nor_c;
|
||||
|
||||
// the Tangents of the Vertices
|
||||
// these are optional and may not be set
|
||||
private bool m_tan_set;
|
||||
private Vector4 m_tan_a;
|
||||
private Vector4 m_tan_b;
|
||||
private Vector4 m_tan_c;
|
||||
|
||||
public Triangle(Vector3 posa,
|
||||
Vector3 posb,
|
||||
Vector3 posc)
|
||||
{
|
||||
this.m_pos_a = posa;
|
||||
this.m_pos_b = posb;
|
||||
this.m_pos_c = posc;
|
||||
|
||||
this.m_uv_set = false;
|
||||
this.m_uv_a = Vector2.zero;
|
||||
this.m_uv_b = Vector2.zero;
|
||||
this.m_uv_c = Vector2.zero;
|
||||
|
||||
this.m_nor_set = false;
|
||||
this.m_nor_a = Vector3.zero;
|
||||
this.m_nor_b = Vector3.zero;
|
||||
this.m_nor_c = Vector3.zero;
|
||||
|
||||
this.m_tan_set = false;
|
||||
this.m_tan_a = Vector4.zero;
|
||||
this.m_tan_b = Vector4.zero;
|
||||
this.m_tan_c = Vector4.zero;
|
||||
}
|
||||
|
||||
public Vector3 positionA {
|
||||
get { return this.m_pos_a; }
|
||||
}
|
||||
|
||||
public Vector3 positionB {
|
||||
get { return this.m_pos_b; }
|
||||
}
|
||||
|
||||
public Vector3 positionC {
|
||||
get { return this.m_pos_c; }
|
||||
}
|
||||
|
||||
public bool hasUV {
|
||||
get { return this.m_uv_set; }
|
||||
}
|
||||
|
||||
public void SetUV(Vector2 uvA, Vector2 uvB, Vector2 uvC) {
|
||||
this.m_uv_a = uvA;
|
||||
this.m_uv_b = uvB;
|
||||
this.m_uv_c = uvC;
|
||||
|
||||
this.m_uv_set = true;
|
||||
}
|
||||
|
||||
public Vector2 uvA {
|
||||
get { return this.m_uv_a; }
|
||||
}
|
||||
|
||||
public Vector2 uvB {
|
||||
get { return this.m_uv_b; }
|
||||
}
|
||||
|
||||
public Vector2 uvC {
|
||||
get { return this.m_uv_c; }
|
||||
}
|
||||
|
||||
public bool hasNormal {
|
||||
get { return this.m_nor_set; }
|
||||
}
|
||||
|
||||
public void SetNormal(Vector3 norA, Vector3 norB, Vector3 norC) {
|
||||
this.m_nor_a = norA;
|
||||
this.m_nor_b = norB;
|
||||
this.m_nor_c = norC;
|
||||
|
||||
this.m_nor_set = true;
|
||||
}
|
||||
|
||||
public Vector3 normalA {
|
||||
get { return this.m_nor_a; }
|
||||
}
|
||||
|
||||
public Vector3 normalB {
|
||||
get { return this.m_nor_b; }
|
||||
}
|
||||
|
||||
public Vector3 normalC {
|
||||
get { return this.m_nor_c; }
|
||||
}
|
||||
|
||||
public bool hasTangent {
|
||||
get { return this.m_tan_set; }
|
||||
}
|
||||
|
||||
public void SetTangent(Vector4 tanA, Vector4 tanB, Vector4 tanC) {
|
||||
this.m_tan_a = tanA;
|
||||
this.m_tan_b = tanB;
|
||||
this.m_tan_c = tanC;
|
||||
|
||||
this.m_tan_set = true;
|
||||
}
|
||||
|
||||
public Vector4 tangentA {
|
||||
get { return this.m_tan_a; }
|
||||
}
|
||||
|
||||
public Vector4 tangentB {
|
||||
get { return this.m_tan_b; }
|
||||
}
|
||||
|
||||
public Vector4 tangentC {
|
||||
get { return this.m_tan_c; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute and set the tangents of this triangle
|
||||
* Derived From https://answers.unity.com/questions/7789/calculating-tangents-vector4.html
|
||||
*/
|
||||
public void ComputeTangents() {
|
||||
// computing tangents requires both UV and normals set
|
||||
if (!m_nor_set || !m_uv_set) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 v1 = m_pos_a;
|
||||
Vector3 v2 = m_pos_b;
|
||||
Vector3 v3 = m_pos_c;
|
||||
|
||||
Vector2 w1 = m_uv_a;
|
||||
Vector2 w2 = m_uv_b;
|
||||
Vector2 w3 = m_uv_c;
|
||||
|
||||
float x1 = v2.x - v1.x;
|
||||
float x2 = v3.x - v1.x;
|
||||
float y1 = v2.y - v1.y;
|
||||
float y2 = v3.y - v1.y;
|
||||
float z1 = v2.z - v1.z;
|
||||
float z2 = v3.z - v1.z;
|
||||
|
||||
float s1 = w2.x - w1.x;
|
||||
float s2 = w3.x - w1.x;
|
||||
float t1 = w2.y - w1.y;
|
||||
float t2 = w3.y - w1.y;
|
||||
|
||||
float r = 1.0f / (s1 * t2 - s2 * t1);
|
||||
|
||||
Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
|
||||
Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
|
||||
|
||||
Vector3 n1 = m_nor_a;
|
||||
Vector3 nt1 = sdir;
|
||||
|
||||
Vector3.OrthoNormalize(ref n1, ref nt1);
|
||||
Vector4 tanA = new Vector4(nt1.x, nt1.y, nt1.z, (Vector3.Dot(Vector3.Cross(n1, nt1), tdir) < 0.0f) ? -1.0f : 1.0f);
|
||||
|
||||
Vector3 n2 = m_nor_b;
|
||||
Vector3 nt2 = sdir;
|
||||
|
||||
Vector3.OrthoNormalize(ref n2, ref nt2);
|
||||
Vector4 tanB = new Vector4(nt2.x, nt2.y, nt2.z, (Vector3.Dot(Vector3.Cross(n2, nt2), tdir) < 0.0f) ? -1.0f : 1.0f);
|
||||
|
||||
Vector3 n3 = m_nor_c;
|
||||
Vector3 nt3 = sdir;
|
||||
|
||||
Vector3.OrthoNormalize(ref n3, ref nt3);
|
||||
Vector4 tanC = new Vector4(nt3.x, nt3.y, nt3.z, (Vector3.Dot(Vector3.Cross(n3, nt3), tdir) < 0.0f) ? -1.0f : 1.0f);
|
||||
|
||||
// finally set the tangents of this object
|
||||
SetTangent(tanA, tanB, tanC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the Barycentric coordinate weight values u-v-w for Point p in respect to the provided
|
||||
* triangle. This is useful for computing new UV coordinates for arbitrary points.
|
||||
*/
|
||||
public Vector3 Barycentric(Vector3 p) {
|
||||
Vector3 a = m_pos_a;
|
||||
Vector3 b = m_pos_b;
|
||||
Vector3 c = m_pos_c;
|
||||
|
||||
Vector3 m = Vector3.Cross(b - a, c - a);
|
||||
|
||||
float nu;
|
||||
float nv;
|
||||
float ood;
|
||||
|
||||
float x = Mathf.Abs(m.x);
|
||||
float y = Mathf.Abs(m.y);
|
||||
float z = Mathf.Abs(m.z);
|
||||
|
||||
// compute areas of plane with largest projections
|
||||
if (x >= y && x >= z) {
|
||||
// area of PBC in yz plane
|
||||
nu = Intersector.TriArea2D(p.y, p.z, b.y, b.z, c.y, c.z);
|
||||
// area of PCA in yz plane
|
||||
nv = Intersector.TriArea2D(p.y, p.z, c.y, c.z, a.y, a.z);
|
||||
// 1/2*area of ABC in yz plane
|
||||
ood = 1.0f / m.x;
|
||||
}
|
||||
else if (y >= x && y >= z) {
|
||||
// project in xz plane
|
||||
nu = Intersector.TriArea2D(p.x, p.z, b.x, b.z, c.x, c.z);
|
||||
nv = Intersector.TriArea2D(p.x, p.z, c.x, c.z, a.x, a.z);
|
||||
ood = 1.0f / -m.y;
|
||||
}
|
||||
else {
|
||||
// project in xy plane
|
||||
nu = Intersector.TriArea2D(p.x, p.y, b.x, b.y, c.x, c.y);
|
||||
nv = Intersector.TriArea2D(p.x, p.y, c.x, c.y, a.x, a.y);
|
||||
ood = 1.0f / m.z;
|
||||
}
|
||||
|
||||
float u = nu * ood;
|
||||
float v = nv * ood;
|
||||
float w = 1.0f - u - v;
|
||||
|
||||
return new Vector3(u, v, w);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a set of new UV coordinates for the provided point pt in respect to Triangle.
|
||||
*
|
||||
* Uses weight values for the computation, so this triangle must have UV's set to return
|
||||
* the correct results. Otherwise Vector2.zero will be returned. check via hasUV().
|
||||
*/
|
||||
public Vector2 GenerateUV(Vector3 pt) {
|
||||
// if not set, result will be zero, quick exit
|
||||
if (!m_uv_set) {
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
Vector3 weights = Barycentric(pt);
|
||||
|
||||
return (weights.x * m_uv_a) + (weights.y * m_uv_b) + (weights.z * m_uv_c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a set of new Normal coordinates for the provided point pt in respect to Triangle.
|
||||
*
|
||||
* Uses weight values for the computation, so this triangle must have Normal's set to return
|
||||
* the correct results. Otherwise Vector3.zero will be returned. check via hasNormal().
|
||||
*/
|
||||
public Vector3 GenerateNormal(Vector3 pt) {
|
||||
// if not set, result will be zero, quick exit
|
||||
if (!m_nor_set) {
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
Vector3 weights = Barycentric(pt);
|
||||
|
||||
return (weights.x * m_nor_a) + (weights.y * m_nor_b) + (weights.z * m_nor_c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a set of new Tangent coordinates for the provided point pt in respect to Triangle.
|
||||
*
|
||||
* Uses weight values for the computation, so this triangle must have Tangent's set to return
|
||||
* the correct results. Otherwise Vector4.zero will be returned. check via hasTangent().
|
||||
*/
|
||||
public Vector4 GenerateTangent(Vector3 pt) {
|
||||
// if not set, result will be zero, quick exit
|
||||
if (!m_nor_set) {
|
||||
return Vector4.zero;
|
||||
}
|
||||
|
||||
Vector3 weights = Barycentric(pt);
|
||||
|
||||
return (weights.x * m_tan_a) + (weights.y * m_tan_b) + (weights.z * m_tan_c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to split this triangle by the provided plane and store
|
||||
* the results inside the IntersectionResult structure.
|
||||
* Returns true on success or false otherwise
|
||||
*/
|
||||
public bool Split(Plane pl, IntersectionResult result) {
|
||||
Intersector.Intersect(pl, this, result);
|
||||
|
||||
return result.isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the triangle winding order, if it's Clock Wise or Counter Clock Wise
|
||||
*/
|
||||
public bool IsCW() {
|
||||
return SignedSquare(m_pos_a, m_pos_b, m_pos_c) >= float.Epsilon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Signed square of a given triangle, useful for checking the
|
||||
* winding order
|
||||
*/
|
||||
public static float SignedSquare(Vector3 a, Vector3 b, Vector3 c) {
|
||||
return (a.x * (b.y * c.z - b.z * c.y) -
|
||||
a.y * (b.x * c.z - b.z * c.x) +
|
||||
a.z * (b.x * c.y - b.y * c.x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Editor only DEBUG functionality. This should not be compiled in the final
|
||||
* Version.
|
||||
*/
|
||||
public void OnDebugDraw() {
|
||||
OnDebugDraw(Color.white);
|
||||
}
|
||||
|
||||
public void OnDebugDraw(Color drawColor) {
|
||||
#if UNITY_EDITOR
|
||||
Color prevColor = Gizmos.color;
|
||||
|
||||
Gizmos.color = drawColor;
|
||||
|
||||
Gizmos.DrawLine(positionA, positionB);
|
||||
Gizmos.DrawLine(positionB, positionC);
|
||||
Gizmos.DrawLine(positionC, positionA);
|
||||
|
||||
Gizmos.color = prevColor;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 631906439500e4795907654a51e7e4c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 40995
|
||||
packageName: Game Kit Controller - Shooter Melee Adventure FPS TPS Creator 3D +
|
||||
2.5D
|
||||
packageVersion: 3.77h
|
||||
assetPath: Assets/Game Kit Controller/Integrations/EzySlice/Framework/Triangle.cs
|
||||
uploadId: 889948
|
||||
@@ -0,0 +1,201 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EzySlice {
|
||||
|
||||
/**
|
||||
* Contains static functionality for performing Triangulation on arbitrary vertices.
|
||||
* Read the individual function descriptions for specific details.
|
||||
*/
|
||||
public sealed class Triangulator {
|
||||
|
||||
/**
|
||||
* Represents a 3D Vertex which has been mapped onto a 2D surface
|
||||
* and is mainly used in MonotoneChain to triangulate a set of vertices
|
||||
* against a flat plane.
|
||||
*/
|
||||
internal struct Mapped2D {
|
||||
private readonly Vector3 original;
|
||||
private readonly Vector2 mapped;
|
||||
|
||||
public Mapped2D(Vector3 newOriginal, Vector3 u, Vector3 v) {
|
||||
this.original = newOriginal;
|
||||
this.mapped = new Vector2(Vector3.Dot(newOriginal, u), Vector3.Dot(newOriginal, v));
|
||||
}
|
||||
|
||||
public Vector2 mappedValue {
|
||||
get { return this.mapped; }
|
||||
}
|
||||
|
||||
public Vector3 originalValue {
|
||||
get { return this.original; }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded variant of MonotoneChain which will calculate UV coordinates of the Triangles
|
||||
* between 0.0 and 1.0 (default).
|
||||
*
|
||||
* See MonotoneChain(vertices, normal, tri, TextureRegion) for full explanation
|
||||
*/
|
||||
public static bool MonotoneChain(List<Vector3> vertices, Vector3 normal, out List<Triangle> tri) {
|
||||
// default texture region is in coordinates 0,0 to 1,1
|
||||
return MonotoneChain(vertices, normal, out tri, new TextureRegion(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* O(n log n) Convex Hull Algorithm.
|
||||
* Accepts a list of vertices as Vector3 and triangulates them according to a projection
|
||||
* plane defined as planeNormal. Algorithm will output vertices, indices and UV coordinates
|
||||
* as arrays
|
||||
*/
|
||||
public static bool MonotoneChain(List<Vector3> vertices, Vector3 normal, out List<Triangle> tri, TextureRegion texRegion) {
|
||||
int count = vertices.Count;
|
||||
|
||||
// we cannot triangulate less than 3 points. Use minimum of 3 points
|
||||
if (count < 3) {
|
||||
tri = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// first, we map from 3D points into a 2D plane represented by the provided normal
|
||||
Vector3 u = Vector3.Normalize(Vector3.Cross(normal, Vector3.up));
|
||||
if ( Vector3.zero == u)
|
||||
{
|
||||
u = Vector3.Normalize(Vector3.Cross(normal, Vector3.forward));
|
||||
}
|
||||
Vector3 v = Vector3.Cross(u, normal);
|
||||
|
||||
// generate an array of mapped values
|
||||
Mapped2D[] mapped = new Mapped2D[count];
|
||||
|
||||
// these values will be used to generate new UV coordinates later on
|
||||
float maxDivX = float.MinValue;
|
||||
float maxDivY = float.MinValue;
|
||||
float minDivX = float.MaxValue;
|
||||
float minDivY = float.MaxValue;
|
||||
|
||||
// map the 3D vertices into the 2D mapped values
|
||||
for (int i = 0; i < count; i++) {
|
||||
Vector3 vertToAdd = vertices[i];
|
||||
|
||||
Mapped2D newMappedValue = new Mapped2D(vertToAdd, u, v);
|
||||
Vector2 mapVal = newMappedValue.mappedValue;
|
||||
|
||||
// grab our maximal values so we can map UV's in a proper range
|
||||
maxDivX = Mathf.Max(maxDivX, mapVal.x);
|
||||
maxDivY = Mathf.Max(maxDivY, mapVal.y);
|
||||
minDivX = Mathf.Min(minDivX, mapVal.x);
|
||||
minDivY = Mathf.Min(minDivY, mapVal.y);
|
||||
|
||||
mapped[i] = newMappedValue;
|
||||
}
|
||||
|
||||
// sort our newly generated array values
|
||||
Array.Sort<Mapped2D>(mapped, (a, b) =>
|
||||
{
|
||||
Vector2 x = a.mappedValue;
|
||||
Vector2 p = b.mappedValue;
|
||||
|
||||
return (x.x < p.x || (x.x == p.x && x.y < p.y)) ? -1 : 1;
|
||||
});
|
||||
|
||||
// our final hull mappings will end up in here
|
||||
Mapped2D[] hulls = new Mapped2D[count+1];
|
||||
|
||||
int k = 0;
|
||||
|
||||
// build the lower hull of the chain
|
||||
for (int i = 0; i < count; i++) {
|
||||
while (k >= 2) {
|
||||
Vector2 mA = hulls[k - 2].mappedValue;
|
||||
Vector2 mB = hulls[k - 1].mappedValue;
|
||||
Vector2 mC = mapped[i].mappedValue;
|
||||
|
||||
if (Intersector.TriArea2D(mA.x, mA.y, mB.x, mB.y, mC.x, mC.y) > 0.0f) {
|
||||
break;
|
||||
}
|
||||
|
||||
k--;
|
||||
}
|
||||
|
||||
hulls[k++] = mapped[i];
|
||||
}
|
||||
|
||||
// build the upper hull of the chain
|
||||
for (int i = count - 2, t = k + 1; i >= 0; i--) {
|
||||
while (k >= t) {
|
||||
Vector2 mA = hulls[k - 2].mappedValue;
|
||||
Vector2 mB = hulls[k - 1].mappedValue;
|
||||
Vector2 mC = mapped[i].mappedValue;
|
||||
|
||||
if (Intersector.TriArea2D(mA.x, mA.y, mB.x, mB.y, mC.x, mC.y) > 0.0f) {
|
||||
break;
|
||||
}
|
||||
|
||||
k--;
|
||||
}
|
||||
|
||||
hulls[k++] = mapped[i];
|
||||
}
|
||||
|
||||
// finally we can build our mesh, generate all the variables
|
||||
// and fill them up
|
||||
int vertCount = k - 1;
|
||||
int triCount = (vertCount - 2) * 3;
|
||||
|
||||
// this should not happen, but here just in case
|
||||
if (vertCount < 3) {
|
||||
tri = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ensure List does not dynamically grow, performing copy ops each time!
|
||||
tri = new List<Triangle>(triCount / 3);
|
||||
|
||||
float width = maxDivX - minDivX;
|
||||
float height = maxDivY - minDivY;
|
||||
|
||||
int indexCount = 1;
|
||||
|
||||
// generate both the vertices and uv's in this loop
|
||||
for (int i = 0; i < triCount; i+=3) {
|
||||
// the Vertices in our triangle
|
||||
Mapped2D posA = hulls[0];
|
||||
Mapped2D posB = hulls[indexCount];
|
||||
Mapped2D posC = hulls[indexCount + 1];
|
||||
|
||||
// generate UV Maps
|
||||
Vector2 uvA = posA.mappedValue;
|
||||
Vector2 uvB = posB.mappedValue;
|
||||
Vector2 uvC = posC.mappedValue;
|
||||
|
||||
uvA.x = (uvA.x - minDivX) / width;
|
||||
uvA.y = (uvA.y - minDivY) / height;
|
||||
|
||||
uvB.x = (uvB.x - minDivX) / width;
|
||||
uvB.y = (uvB.y - minDivY) / height;
|
||||
|
||||
uvC.x = (uvC.x - minDivX) / width;
|
||||
uvC.y = (uvC.y - minDivY) / height;
|
||||
|
||||
Triangle newTriangle = new Triangle(posA.originalValue, posB.originalValue, posC.originalValue);
|
||||
|
||||
// ensure our UV coordinates are mapped into the requested TextureRegion
|
||||
newTriangle.SetUV(texRegion.Map(uvA), texRegion.Map(uvB), texRegion.Map(uvC));
|
||||
|
||||
// the normals is the same for all vertices since the final mesh is completly flat
|
||||
newTriangle.SetNormal(normal, normal, normal);
|
||||
newTriangle.ComputeTangents();
|
||||
|
||||
tri.Add(newTriangle);
|
||||
|
||||
indexCount++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b3517c604b184880b3e9ab1264a1062
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 40995
|
||||
packageName: Game Kit Controller - Shooter Melee Adventure FPS TPS Creator 3D +
|
||||
2.5D
|
||||
packageVersion: 3.77h
|
||||
assetPath: Assets/Game Kit Controller/Integrations/EzySlice/Framework/Triangulator.cs
|
||||
uploadId: 889948
|
||||
Reference in New Issue
Block a user