[add] Added TriangleElement.

This commit is contained in:
falsycat 2019-10-15 00:00:00 +00:00
parent 3d992ee73b
commit 928be56f10
4 changed files with 97 additions and 6 deletions

View File

@ -38,7 +38,8 @@ class Context {
import sjplayer.BackgroundScheduledController, import sjplayer.BackgroundScheduledController,
sjplayer.CircleElement, sjplayer.CircleElement,
sjplayer.SquareElement; sjplayer.SquareElement,
sjplayer.TriangleElement;
auto factories = tuple( auto factories = tuple(
tuple( tuple(
"actor", "actor",
@ -61,6 +62,10 @@ class Context {
"square", "square",
SquareElementScheduledControllerFactory(programs, varstore), SquareElementScheduledControllerFactory(programs, varstore),
), ),
tuple(
"triangle",
TriangleElementScheduledControllerFactory(programs, varstore),
),
tuple( tuple(
"variable", "variable",
VarStoreScheduledControllerFactory(varstore), VarStoreScheduledControllerFactory(varstore),

View File

@ -8,7 +8,8 @@ import sjplayer.Actor,
sjplayer.Background, sjplayer.Background,
sjplayer.CircleElement, sjplayer.CircleElement,
sjplayer.PostEffect, sjplayer.PostEffect,
sjplayer.SquareElement; sjplayer.SquareElement,
sjplayer.TriangleElement;
/// ///
class ProgramSet { class ProgramSet {
@ -20,6 +21,7 @@ class ProgramSet {
CircleElementProgram, CircleElementProgram,
PostEffectProgram, PostEffectProgram,
SquareElementProgram, SquareElementProgram,
TriangleElementProgram,
); );
/// ///

View File

@ -0,0 +1,83 @@
/// License: MIT
module sjplayer.TriangleElement;
import std.algorithm,
std.math,
std.typecons;
import gl4d;
import sjplayer.AbstractShapeElement,
sjplayer.ElementInterface,
sjplayer.ShapeElementDrawer,
sjplayer.ShapeElementProgram,
sjplayer.ShapeElementScheduledController,
sjplayer.util.linalg;
///
class TriangleElement : AbstractShapeElement {
public:
override DamageCalculationResult CalculateDamage(vec2 p1, vec2 p2) const {
if (!alive) return DamageCalculationResult(0, 0);
const m = matrix.inverse;
const a = (m * vec3(p1, 1)).xy;
const b = (m * vec3(p2, 1)).xy;
enum A = vec2( 0, sqrt(3f)*2f/3f);
enum B = vec2(-1, -sqrt(3f) /3f);
enum C = vec2( 1, -sqrt(3f) /3f);
bool CheckInside(vec2 pt) {
return
cross2(B-A, pt-A) >= 0 && cross2(pt-A, C-A) >= 0 && cross2(C-B, pt-B) >= 0;
}
if (CheckInside(a) || CheckInside(b)) {
return DamageCalculationResult(damage, 0);
}
enum edges = [
tuple(A, B),
tuple(A, C),
tuple(B, C),
];
float[3] distances;
static foreach (i, edge; edges) {
distances[i] = CalculateDistance2LineSegment(edge[0], edge[1], a, b);
}
const min_distance = distances[].minElement;
if (min_distance == 0) {
return DamageCalculationResult(damage, 0);
}
return DamageCalculationResult(0, 1-(min_distance-1).clamp(0f, 1f));
}
}
///
alias TriangleElementDrawer = ShapeElementDrawer!(
TriangleElementProgram,
[vec2(-1, 1.2), vec2(-1, -1), vec2(1, -1), vec2(1, 1.2)]);
///
alias TriangleElementProgram = ShapeElementProgram!(q{
vec2 A = vec2( 0, sqrt(3)*2/3);
vec2 B = vec2(-1, -sqrt(3) /3);
vec2 C = vec2( 1, -sqrt(3) /3);
vec2 AB = B - A;
vec2 AC = C - A;
vec2 BC = C - B;
float cross_AB = AB.x * (uv_.y - A.y) - AB.y * (uv_.x - A.x);
float cross_AC = (uv_.x - A.x) * AC.y - (uv_.y - A.y) * AC.x;
float cross_BC = BC.x * (uv_.y - B.y) - BC.y * (uv_.x - B.x);
return step(0, cross_AB) * step(0, cross_AC) * step(0, cross_BC);
});
///
alias TriangleElementScheduledControllerFactory =
ShapeElementScheduledControllerFactory!(
TriangleElement,
TriangleElementDrawer);

View File

@ -33,10 +33,6 @@ unittest {
/// ///
float CalculateDistance2LineSegment(vec2 a1, vec2 b1, vec2 a2, vec2 b2) { float CalculateDistance2LineSegment(vec2 a1, vec2 b1, vec2 a2, vec2 b2) {
float cross2(vec2 v1, vec2 v2) {
return v1.x * v2.y - v1.y * v2.x;
}
if (a1 == b1) return CalculateDistanceOriginAndLineSegment(a2 - a1, b2 - a1); if (a1 == b1) return CalculateDistanceOriginAndLineSegment(a2 - a1, b2 - a1);
if (a2 == b2) return CalculateDistanceOriginAndLineSegment(a1 - a2, b1 - a2); if (a2 == b2) return CalculateDistanceOriginAndLineSegment(a1 - a2, b1 - a2);
@ -77,3 +73,8 @@ unittest {
assert(CalculateDistance2LineSegment( assert(CalculateDistance2LineSegment(
vec2(-1, 0), vec2(1, 0), vec2(2, 1), vec2(2, -1)).approxEqual(1f)); vec2(-1, 0), vec2(1, 0), vec2(2, 1), vec2(2, -1)).approxEqual(1f));
} }
///
float cross2(vec2 v1, vec2 v2) {
return v1.x * v2.y - v1.y * v2.x;
}