فهرست منبع

started s3d + trails

ncannasse 8 سال پیش
والد
کامیت
40376fe182
4فایلهای تغییر یافته به همراه360 افزوده شده و 0 حذف شده
  1. 78 0
      h3d/prim/DynamicPrimitive.hx
  2. 147 0
      h3d/scene/Trail.hx
  3. 44 0
      hxd/fmt/s3d/Data.hx
  4. 91 0
      hxd/fmt/s3d/Library.hx

+ 78 - 0
h3d/prim/DynamicPrimitive.hx

@@ -0,0 +1,78 @@
+package h3d.prim;
+
+class DynamicPrimitive extends Primitive {
+
+	var vbuf : hxd.FloatBuffer;
+	var ibuf : hxd.IndexBuffer;
+	var vsize : Int;
+	var isize : Int;
+	var stride : Int;
+
+	public var bounds = new h3d.col.Bounds();
+
+	public function new( stride : Int ) {
+		this.stride = stride;
+	}
+
+	override function getBounds() {
+		return bounds;
+	}
+
+	public function getBuffer( vertices : Int ) {
+		if( vbuf == null ) vbuf = new hxd.FloatBuffer(vertices * stride) else vbuf.grow(vertices * stride);
+		vsize = vertices;
+		return vbuf;
+	}
+
+	public function getIndexes( count : Int ) {
+		if( ibuf == null ) ibuf = new hxd.IndexBuffer(count) else ibuf.grow(count);
+		isize = count;
+		return ibuf;
+	}
+
+	public function flush() {
+		if( vsize == 0 || isize == 0 ) {
+			if( buffer != null ) {
+				buffer.dispose();
+				buffer = null;
+			}
+			if( indexes != null ) {
+				indexes.dispose();
+				indexes = null;
+			}
+			return;
+		}
+
+		if( buffer != null && (buffer.isDisposed() || buffer.vertices < vsize) ) {
+			buffer.dispose();
+			buffer = null;
+		}
+		if( indexes != null && (indexes.isDisposed() || indexes.count < isize) ) {
+			indexes.dispose();
+			indexes = null;
+		}
+
+		if( buffer == null )
+			buffer = new h3d.Buffer(vsize, stride);
+		if( indexes == null )
+			indexes = new h3d.Indexes(isize);
+
+		buffer.uploadVector(vbuf, 0, vsize);
+		indexes.upload(ibuf, 0, isize);
+	}
+
+	override function dispose() {
+		super.dispose();
+		vbuf = null;
+		ibuf = null;
+	}
+
+	override function triCount() {
+		return Std.int(isize / 3);
+	}
+
+	override public function render(engine:h3d.Engine) {
+		if( buffer != null ) engine.renderIndexed(buffer, indexes, 0, triCount());
+	}
+
+}

+ 147 - 0
h3d/scene/Trail.hx

@@ -0,0 +1,147 @@
+package h3d.scene;
+
+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 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 function new(?parent) {
+		dprim = new h3d.prim.DynamicPrimitive(8);
+		super(dprim, null, parent);
+		material.blendMode = SoftAdd;
+		material.mainPass.culling = None;
+		material.mainPass.depthWrite = false;
+	}
+
+	function get_texture() return material.texture;
+	function set_texture(t) return material.texture = t;
+
+	public function save() : Dynamic {
+		return {
+			duration : duration,
+			angle : angle,
+			sizeStart : sizeStart,
+			sizeEnd : sizeEnd,
+			texture : texture == null ? null : texture.name,
+		};
+	}
+
+	public function load( obj : Dynamic ) {
+		for( f in Reflect.fields(obj) ) {
+			var v : Dynamic = Reflect.field(obj, f);
+			switch( f ) {
+			case "texture":
+				texture = v == null ? null : loadTexture(v);
+			default:
+				Reflect.setField(this, f, v);
+			}
+		}
+	}
+
+	function loadTexture( path : String ) {
+		try	{
+			return hxd.res.Loader.currentInstance.load(path).toTexture();
+		} catch( e : hxd.res.NotFound ) {
+			return h3d.mat.Texture.fromColor(0xFF00FF);
+		}
+	}
+
+	override function sync(ctx) {
+		super.sync(ctx);
+		var curX = absPos._41;
+		var curY = absPos._42;
+		var curZ = absPos._43;
+		var curTime = ctx.time;
+
+		// todo : interpolate for softer curves if big step ?
+		var q = new h3d.Quat();
+		q.initRotateMatrix(absPos);
+		points.push({ x : curX, y : curY, z : curZ, q : q, t : curTime });
+
+		var lastTime = curTime - duration;
+		while( points[0].t < lastTime )
+			points.shift();
+
+		if( points.length <= 2 ) {
+			dprim.dispose();
+			return;
+		}
+
+		var buffer = dprim.getBuffer((points.length - 1) * 2);
+		var up = new h3d.col.Point(0, Math.sin(angle), Math.cos(angle));
+
+		var out = 0;
+		var p0 = points[0];
+		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);
+			left.transform3x3(absPos);
+
+			var n = left.cross(delta);
+			var u = (curTime - p0.t) / duration;
+
+			left.scale( hxd.Math.lerp(sizeStart, sizeEnd, u) * 0.5 );
+
+			buffer[out++] = p0.x - left.x;
+			buffer[out++] = p0.y - left.y;
+			buffer[out++] = p0.z - left.z;
+			dprim.bounds.addPos(p0.x - left.x, p0.y - left.y, p0.z - left.z);
+
+			buffer[out++] = n.x;
+			buffer[out++] = n.y;
+			buffer[out++] = n.z;
+
+			buffer[out++] = u;
+			buffer[out++] = 0;
+
+
+			buffer[out++] = p0.x + left.x;
+			buffer[out++] = p0.y + left.y;
+			buffer[out++] = p0.z + left.z;
+			dprim.bounds.addPos(p0.x + left.x, p0.y + left.y, p0.z + left.z);
+
+			buffer[out++] = n.x;
+			buffer[out++] = n.y;
+			buffer[out++] = n.z;
+
+			buffer[out++] = u;
+			buffer[out++] = 1;
+			p0 = p1;
+		}
+
+
+		var idx = dprim.getIndexes((points.length - 2) * 6);
+		var out = 0;
+		for( i in 0...points.length - 2 ) {
+			var p = i * 2;
+			idx[out++] = p;
+			idx[out++] = p + 2;
+			idx[out++] = p + 1;
+
+			idx[out++] = p + 2;
+			idx[out++] = p + 3;
+			idx[out++] = p + 1;
+		}
+
+		absPos.identity();
+		posChanged = true;
+
+		dprim.flush();
+	}
+
+	override function draw(ctx:RenderContext) {
+		if( points.length >= 2 ) super.draw(ctx);
+	}
+
+}

+ 44 - 0
hxd/fmt/s3d/Data.hx

@@ -0,0 +1,44 @@
+package hxd.fmt.s3d;
+
+// an enum would have been better but is less JSON-friendly
+
+@:enum abstract ObjectType(String) {
+	var Object = "object";
+	var Particles = "particles";
+	var Trail = "trail";
+	var Constraint = "constraint";
+}
+
+typedef BaseObject = {
+	var type : ObjectType;
+	var name : String;
+	@:optional var x : Float;
+	@:optional var y : Float;
+	@:optional var z : Float;
+	@:optional var scaleX : Float;
+	@:optional var scaleY : Float;
+	@:optional var scaleZ : Float;
+	@:optional var rotationX : Float;
+	@:optional var rotationY : Float;
+	@:optional var rotationZ : Float;
+	@:optional var children : Array<BaseObject>;
+}
+
+typedef ObjectProperties = {> BaseObject,
+	var modelPath : String;
+	@:optional var animationPath : String;
+	@:optional var lock : Bool;
+}
+
+typedef ConstraintProperties = {> BaseObject,
+	var source : String;
+	var attach : String;
+}
+
+typedef ExtraProperties = {> BaseObject,
+	var data : Dynamic;
+}
+
+typedef Data = {
+	var content : Array<BaseObject>;
+}

+ 91 - 0
hxd/fmt/s3d/Library.hx

@@ -0,0 +1,91 @@
+package hxd.fmt.s3d;
+import hxd.fmt.s3d.Data;
+
+class Library {
+
+	public var data : Data;
+	var cache : h3d.prim.ModelCache;
+
+	public function new( ?cache ) {
+		this.cache = cache;
+		if( this.cache == null ) this.cache = new h3d.prim.ModelCache();
+		data = { content : [] };
+	}
+
+	public function load( content : Dynamic ) {
+		data = content;
+	}
+
+	public function save() {
+		return data;
+	}
+
+	public function makeInstance() {
+		var root = new h3d.scene.Object();
+		for( c in data.content )
+			makeObject(c, root);
+		return root;
+	}
+
+	public function makeObject( o : BaseObject, ?parent : h3d.scene.Object ) {
+		var obj = initObject(o, parent);
+		if( obj == null )
+			return null;
+		obj.name = o.name;
+		if( o.x != null ) obj.x = o.x;
+		if( o.y != null ) obj.y = o.y;
+		if( o.z != null ) obj.z = o.z;
+		if( o.scaleX != null ) obj.scaleX = o.scaleX;
+		if( o.scaleY != null ) obj.scaleY = o.scaleY;
+		if( o.scaleZ != null ) obj.scaleZ = o.scaleZ;
+		obj.setRotate(o.rotationX == null ? 0 : o.rotationX, o.rotationY == null ? 0 : o.rotationY, o.rotationZ == null ? 0 : o.rotationZ);
+		if( parent != null )
+			parent.addChild(obj);
+		if( o.children != null ) {
+			for( c in o.children )
+				makeObject(c, obj);
+		}
+		return obj;
+	}
+
+	function initObject( o : BaseObject, ?parent : h3d.scene.Object ) : h3d.scene.Object {
+		switch( o.type ) {
+		case Object:
+			var p : ObjectProperties = cast o;
+			var obj = loadModel(p.modelPath);
+			if( p.animationPath != null ) {
+				var a = obj.playAnimation(loadAnimation(p.animationPath));
+			}
+			return obj;
+		case Constraint:
+			var root = parent;
+			while( root != null && root.parent != null )
+				root = root.parent;
+			var p : ConstraintProperties = cast o;
+			if( root != null ) {
+				var obj = root.getObjectByName(p.source.split(".").pop());
+				if( obj != null ) obj.follow = root.getObjectByName(p.attach.split(".").pop());
+			}
+			return null;
+		case Particles:
+			var p : ExtraProperties = cast o;
+			var obj = new h3d.parts.GpuParticles();
+			obj.load(p.data);
+			return obj;
+		case Trail:
+			var p : ExtraProperties = cast o;
+			var obj = new h3d.scene.Trail();
+			obj.load(p.data);
+			return obj;
+		}
+	}
+
+	function loadModel( path : String ) : h3d.scene.Object {
+		return cache.loadModel(hxd.res.Loader.currentInstance.load(path).toModel());
+	}
+
+	function loadAnimation( path : String ) : h3d.anim.Animation {
+		return cache.loadAnimation(hxd.res.Loader.currentInstance.load(path).toModel());
+	}
+
+}