|
@@ -1,28 +1,54 @@
|
|
|
package h3d.scene;
|
|
|
|
|
|
+private class TrailElement {
|
|
|
+ public var q : h3d.Quat;
|
|
|
+ public var x : Float;
|
|
|
+ public var y : Float;
|
|
|
+ public var z : Float;
|
|
|
+ public var t : Float;
|
|
|
+ public var size : Float;
|
|
|
+ public function new() {
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
class Trail extends Mesh {
|
|
|
|
|
|
// to optimize : use a proper buffer with slide window
|
|
|
- var points : Array<{ x : Float, y : Float, z : Float, q : h3d.Quat, t : Float }> = [];
|
|
|
+ var points : Array<TrailElement> = [];
|
|
|
var dprim : h3d.prim.DynamicPrimitive;
|
|
|
|
|
|
public var duration : Float = 0.5;
|
|
|
public var angle : Float = 0.;
|
|
|
public var sizeStart : Float = 4.;
|
|
|
public var sizeEnd : Float = 0.;
|
|
|
- public var texture(get,set) : h3d.mat.Texture;
|
|
|
+ public var movementMin : Float = 0.1;
|
|
|
+ public var movementMax : Float = 0.5;
|
|
|
+ public var smoothness : Float = 0.5;
|
|
|
+ public var materialData = {};
|
|
|
+
|
|
|
+ public var texture(get, set) : h3d.mat.Texture;
|
|
|
+ var pending = new TrailElement(); // tmp
|
|
|
|
|
|
public function new(?parent) {
|
|
|
dprim = new h3d.prim.DynamicPrimitive(8);
|
|
|
super(dprim, null, parent);
|
|
|
- material.blendMode = SoftAdd;
|
|
|
- material.mainPass.culling = None;
|
|
|
- material.mainPass.depthWrite = false;
|
|
|
+ material.props = getMaterialProps();
|
|
|
+ material.mainPass.dynamicParameters = true;
|
|
|
}
|
|
|
|
|
|
function get_texture() return material.texture;
|
|
|
function set_texture(t) return material.texture = t;
|
|
|
|
|
|
+ public function getMaterialProps() {
|
|
|
+ var name = h3d.mat.MaterialSetup.current.name;
|
|
|
+ var p = Reflect.field(materialData, name);
|
|
|
+ if( p == null ) {
|
|
|
+ p = h3d.mat.MaterialSetup.current.getDefaults("trail3D");
|
|
|
+ Reflect.setField(materialData, name, p);
|
|
|
+ }
|
|
|
+ return p;
|
|
|
+ }
|
|
|
+
|
|
|
public function save() : Dynamic {
|
|
|
return {
|
|
|
duration : duration,
|
|
@@ -30,6 +56,10 @@ class Trail extends Mesh {
|
|
|
sizeStart : sizeStart,
|
|
|
sizeEnd : sizeEnd,
|
|
|
texture : texture == null ? null : texture.name,
|
|
|
+ movementMin : movementMin,
|
|
|
+ movementMax : movementMax,
|
|
|
+ smoothness : smoothness,
|
|
|
+ material : materialData,
|
|
|
};
|
|
|
}
|
|
|
|
|
@@ -39,6 +69,9 @@ class Trail extends Mesh {
|
|
|
switch( f ) {
|
|
|
case "texture":
|
|
|
texture = v == null ? null : loadTexture(v);
|
|
|
+ case "material":
|
|
|
+ materialData = v;
|
|
|
+ material.props = getMaterialProps();
|
|
|
default:
|
|
|
Reflect.setField(this, f, v);
|
|
|
}
|
|
@@ -60,13 +93,85 @@ class Trail extends Mesh {
|
|
|
var curZ = absPos._43;
|
|
|
var curTime = ctx.time;
|
|
|
|
|
|
- // todo : interpolate for softer curves if big step ?
|
|
|
+ if( pending.size != 0 && points.length == 0 )
|
|
|
+ pending.size = 0;
|
|
|
+
|
|
|
+ if( pending.size != 0 ) {
|
|
|
+
|
|
|
+ // http://scaledinnovation.com/analytics/splines/aboutSplines.html
|
|
|
+
|
|
|
+ var prev = points[points.length - 1];
|
|
|
+
|
|
|
+ var x0 = prev.x;
|
|
|
+ var y0 = prev.y;
|
|
|
+ var z0 = prev.z;
|
|
|
+
|
|
|
+ var x1 = pending.x;
|
|
|
+ var y1 = pending.y;
|
|
|
+ var z1 = pending.z;
|
|
|
+
|
|
|
+ var x2 = curX;
|
|
|
+ var y2 = curY;
|
|
|
+ var z2 = curZ;
|
|
|
+
|
|
|
+ var d01 = hxd.Math.distance(x1 - x0, y1 - y0, z1 - z0);
|
|
|
+ var d12 = hxd.Math.distance(x2 - x1, y2 - y1, z2 - z1);
|
|
|
+
|
|
|
+ var fa = smoothness * d01 / (d01 + d12);
|
|
|
+ var cx = x1 - fa * (x2 - x0);
|
|
|
+ var cy = y1 - fa * (y2 - y0);
|
|
|
+ var cz = z1 - fa * (z2 - z0);
|
|
|
+
|
|
|
+ var dist = d01;
|
|
|
+ var k = Math.ceil(dist / movementMax);
|
|
|
+ if( k > 20 ) k = 20; // max splitting
|
|
|
+
|
|
|
+ for( i in 0...k ) {
|
|
|
+ var v = (i + 1) / k;
|
|
|
+ var q2 = new h3d.Quat();
|
|
|
+ q2.slerp(prev.q, pending.q, v);
|
|
|
+ q2.normalize();
|
|
|
+
|
|
|
+ // bezier
|
|
|
+ var b0 = (1 - v) * (1 - v);
|
|
|
+ var b1 = 2 * v * (1 - v);
|
|
|
+ var b2 = v * v;
|
|
|
+
|
|
|
+ var e = new TrailElement();
|
|
|
+ e.x = x0 * b0 + cx * b1 + x1 * b2;
|
|
|
+ e.y = y0 * b0 + cy * b1 + y1 * b2;
|
|
|
+ e.z = z0 * b0 + cz * b1 + z1 * b2;
|
|
|
+ e.t = hxd.Math.lerp(prev.t, pending.t, v);
|
|
|
+ e.size = 1;
|
|
|
+ e.q = q2;
|
|
|
+ points.push(e);
|
|
|
+ }
|
|
|
+ pending.size = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var prev = points[points.length - 1];
|
|
|
var q = new h3d.Quat();
|
|
|
q.initRotateMatrix(absPos);
|
|
|
- points.push({ x : curX, y : curY, z : curZ, q : q, t : curTime });
|
|
|
+ var dist = prev == null ? 0 : hxd.Math.distanceSq(prev.x - curX, prev.y - curY, prev.z - curZ);
|
|
|
+ var e = null;
|
|
|
+ if( dist < movementMax * movementMax ) {
|
|
|
+ e = new TrailElement();
|
|
|
+ e.size = prev == null || dist > movementMin * movementMin ? 1 : 0;
|
|
|
+ points.push(e);
|
|
|
+ } else {
|
|
|
+ e = pending;
|
|
|
+ e.size = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ e.x = curX;
|
|
|
+ e.y = curY;
|
|
|
+ e.z = curZ;
|
|
|
+ e.t = curTime;
|
|
|
+ e.q = q;
|
|
|
|
|
|
var lastTime = curTime - duration;
|
|
|
- while( points[0].t < lastTime )
|
|
|
+ while( points.length > 0 && points[0].t < lastTime && (points.length > 1 || pending.size != 0) )
|
|
|
points.shift();
|
|
|
|
|
|
if( points.length <= 2 ) {
|
|
@@ -79,19 +184,22 @@ class Trail extends Mesh {
|
|
|
|
|
|
var out = 0;
|
|
|
var p0 = points[0];
|
|
|
+ var delta = new h3d.col.Point(1, 0, 0);
|
|
|
+ var leftSave = up.cross(delta);
|
|
|
+ var left = new h3d.col.Point();
|
|
|
dprim.bounds.empty();
|
|
|
for( i in 1...points.length ) {
|
|
|
var p1 = points[i];
|
|
|
- var delta = new h3d.col.Point(p1.x - p0.x, p1.y - p0.y, p1.z - p0.z);
|
|
|
- delta.normalizeFast();
|
|
|
- var left = up.cross(delta);
|
|
|
- p0.q.initRotateMatrix(absPos);
|
|
|
+ var dist2 = hxd.Math.distanceSq(p1.x - p0.x, p1.y - p0.y, p1.z - p0.z);
|
|
|
+ left.load(leftSave);
|
|
|
+ p0.q.saveToMatrix(absPos);
|
|
|
left.transform3x3(absPos);
|
|
|
|
|
|
var n = left.cross(delta);
|
|
|
var u = (curTime - p0.t) / duration;
|
|
|
|
|
|
- left.scale( hxd.Math.lerp(sizeStart, sizeEnd, u) * 0.5 );
|
|
|
+ var size = hxd.Math.lerp(sizeStart, sizeEnd, u) * 0.5 * p1.size;
|
|
|
+ left.scale(size);
|
|
|
|
|
|
buffer[out++] = p0.x - left.x;
|
|
|
buffer[out++] = p0.y - left.y;
|
|
@@ -134,14 +242,16 @@ class Trail extends Mesh {
|
|
|
idx[out++] = p + 1;
|
|
|
}
|
|
|
|
|
|
- absPos.identity();
|
|
|
- posChanged = true;
|
|
|
-
|
|
|
dprim.flush();
|
|
|
}
|
|
|
|
|
|
override function draw(ctx:RenderContext) {
|
|
|
- if( points.length >= 2 ) super.draw(ctx);
|
|
|
+ if( points.length >= 2 ) {
|
|
|
+ absPos.identity();
|
|
|
+ posChanged = true;
|
|
|
+ ctx.uploadParams();
|
|
|
+ super.draw(ctx);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
}
|