Repe [T3DU] Update - 31f26d171bba0355ce2a77031e3aad4c64dbc7e9
This commit is contained in:
@ -1,31 +1,119 @@
|
||||
package iron.object;
|
||||
|
||||
import iron.data.SceneFormat;
|
||||
import iron.math.Vec4;
|
||||
import iron.math.Quat;
|
||||
|
||||
class Constraint {
|
||||
var raw: TConstraint;
|
||||
var target: Transform = null;
|
||||
|
||||
public function new(constr: TConstraint) {
|
||||
raw = constr;
|
||||
public function new(constraint: TConstraint) {
|
||||
raw = constraint;
|
||||
}
|
||||
|
||||
public function apply(transform: Transform) {
|
||||
if (target == null && raw.target != null) target = Scene.active.getChild(raw.target).transform;
|
||||
|
||||
if (target == null && raw.type != "LIMIT_LOCATION" && raw.type != "LIMIT_ROTATION" && raw.type != "LIMIT_SCALE") return;
|
||||
|
||||
if (raw.type == "COPY_LOCATION") {
|
||||
if (raw.use_x) {
|
||||
transform.world._30 = target.loc.x;
|
||||
if (raw.use_offset) transform.world._30 += transform.loc.x;
|
||||
if (raw.use_offset) {
|
||||
if (raw.use_x) transform.world._30 += target.world._30;
|
||||
if (raw.use_y) transform.world._31 += target.world._31;
|
||||
if (raw.use_z) transform.world._32 += target.world._32;
|
||||
}
|
||||
if (raw.use_y) {
|
||||
transform.world._31 = target.loc.y;
|
||||
if (raw.use_offset) transform.world._31 += transform.loc.y;
|
||||
else {
|
||||
if (raw.use_x) transform.world._30 = target.world._30;
|
||||
if (raw.use_y) transform.world._31 = target.world._31;
|
||||
if (raw.use_z) transform.world._32 = target.world._32;
|
||||
}
|
||||
if (raw.use_z) {
|
||||
transform.world._32 = target.loc.z;
|
||||
if (raw.use_offset) transform.world._32 += transform.loc.z;
|
||||
}
|
||||
|
||||
else if (raw.type == "COPY_ROTATION") {
|
||||
var tq = target.rot;
|
||||
var mq = transform.rot;
|
||||
if (raw.use_offset) {
|
||||
mq.mult(tq);
|
||||
}
|
||||
else {
|
||||
if (raw.use_x) mq.x = tq.x;
|
||||
if (raw.use_y) mq.y = tq.y;
|
||||
if (raw.use_z) mq.z = tq.z;
|
||||
mq.w = tq.w;
|
||||
}
|
||||
var loc = new Vec4(transform.world._30, transform.world._31, transform.world._32);
|
||||
var scale = transform.scale;
|
||||
transform.world.compose(loc, mq, scale);
|
||||
}
|
||||
|
||||
else if (raw.type == "COPY_SCALE") {
|
||||
var ts = target.scale;
|
||||
if (raw.use_offset) {
|
||||
if (raw.use_x) transform.scale.x *= ts.x;
|
||||
if (raw.use_y) transform.scale.y *= ts.y;
|
||||
if (raw.use_z) transform.scale.z *= ts.z;
|
||||
}
|
||||
else {
|
||||
if (raw.use_x) transform.scale.x = ts.x;
|
||||
if (raw.use_y) transform.scale.y = ts.y;
|
||||
if (raw.use_z) transform.scale.z = ts.z;
|
||||
}
|
||||
var loc = new Vec4(transform.world._30, transform.world._31, transform.world._32);
|
||||
transform.world.compose(loc, transform.rot, transform.scale);
|
||||
}
|
||||
|
||||
else if (raw.type == "COPY_TRANSFORMS") {
|
||||
transform.world.setFrom(target.world);
|
||||
}
|
||||
|
||||
else if (raw.type == "LIMIT_LOCATION") {
|
||||
if (raw.use_min_x && transform.world._30 < raw.min_x) transform.world._30 = raw.min_x;
|
||||
if (raw.use_max_x && transform.world._30 > raw.max_x) transform.world._30 = raw.max_x;
|
||||
|
||||
if (raw.use_min_y && transform.world._31 < raw.min_y) transform.world._31 = raw.min_y;
|
||||
if (raw.use_max_y && transform.world._31 > raw.max_y) transform.world._31 = raw.max_y;
|
||||
|
||||
if (raw.use_min_z && transform.world._32 < raw.min_z) transform.world._32 = raw.min_z;
|
||||
if (raw.use_max_z && transform.world._32 > raw.max_z) transform.world._32 = raw.max_z;
|
||||
}
|
||||
|
||||
else if (raw.type == "LIMIT_ROTATION") {
|
||||
var euler = transform.rot.getEuler();
|
||||
var changed = false;
|
||||
|
||||
if (raw.use_limit_x) {
|
||||
if (euler.x < raw.min_x) { euler.x = raw.min_x; changed = true; }
|
||||
if (euler.x > raw.max_x) { euler.x = raw.max_x; changed = true; }
|
||||
}
|
||||
if (raw.use_limit_y) {
|
||||
if (euler.y < raw.min_y) { euler.y = raw.min_y; changed = true; }
|
||||
if (euler.y > raw.max_y) { euler.y = raw.max_y; changed = true; }
|
||||
}
|
||||
if (raw.use_limit_z) {
|
||||
if (euler.z < raw.min_z) { euler.z = raw.min_z; changed = true; }
|
||||
if (euler.z > raw.max_z) { euler.z = raw.max_z; changed = true; }
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
transform.rot.fromEuler(euler.x, euler.y, euler.z);
|
||||
var loc = new Vec4(transform.world._30, transform.world._31, transform.world._32);
|
||||
transform.world.compose(loc, transform.rot, transform.scale);
|
||||
}
|
||||
}
|
||||
|
||||
else if (raw.type == "LIMIT_SCALE") {
|
||||
if (raw.use_min_x && transform.scale.x < raw.min_x) transform.scale.x = raw.min_x;
|
||||
if (raw.use_max_x && transform.scale.x > raw.max_x) transform.scale.x = raw.max_x;
|
||||
|
||||
if (raw.use_min_y && transform.scale.y < raw.min_y) transform.scale.y = raw.min_y;
|
||||
if (raw.use_max_y && transform.scale.y > raw.max_y) transform.scale.y = raw.max_y;
|
||||
|
||||
if (raw.use_min_z && transform.scale.z < raw.min_z) transform.scale.z = raw.min_z;
|
||||
if (raw.use_max_z && transform.scale.z > raw.max_z) transform.scale.z = raw.max_z;
|
||||
|
||||
var loc = new Vec4(transform.world._30, transform.world._31, transform.world._32);
|
||||
transform.world.compose(loc, transform.rot, transform.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1338
leenkx/Sources/iron/object/CurveObject.hx
Normal file
1338
leenkx/Sources/iron/object/CurveObject.hx
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,6 +11,12 @@ import iron.object.CameraObject;
|
||||
class LightObject extends Object {
|
||||
|
||||
public var data: LightData;
|
||||
public var color: Vec4;
|
||||
public var strength: Float;
|
||||
#if lnx_spot
|
||||
public var size: Float;
|
||||
public var blend: Float;
|
||||
#end
|
||||
|
||||
#if rp_shadowmap
|
||||
#if lnx_shadowmap_atlas
|
||||
@ -79,6 +85,15 @@ class LightObject extends Object {
|
||||
super();
|
||||
|
||||
this.data = data;
|
||||
this.color = new Vec4(data.raw.color[0], data.raw.color[1], data.raw.color[2]);
|
||||
this.strength = data.raw.strength;
|
||||
|
||||
#if lnx_spot
|
||||
if (data.raw.type == "spot"){
|
||||
this.size = data.raw.spot_size;
|
||||
this.blend = data.raw.spot_blend;
|
||||
}
|
||||
#end
|
||||
|
||||
var type = data.raw.type;
|
||||
var fov = data.raw.fov;
|
||||
@ -374,7 +389,7 @@ class LightObject extends Object {
|
||||
// Centralize discarding conditions when iterating over lights
|
||||
// Important to avoid issues later with "misaligned" data in uniforms (lightsArray, clusterData, LWVPSpotArray)
|
||||
public inline static function discardLight(light: LightObject) {
|
||||
return !light.visible || light.data.raw.strength == 0.0 || light.data.raw.type == "sun";
|
||||
return !light.visible || light.strength == 0.0 || light.data.raw.type == "sun";
|
||||
}
|
||||
// Discarding conditions but with culling included
|
||||
public inline static function discardLightCulled(light: LightObject) {
|
||||
@ -457,7 +472,7 @@ class LightObject extends Object {
|
||||
lpos.set(l.transform.worldx(), l.transform.worldy(), l.transform.worldz());
|
||||
lpos.applymat4(camera.V);
|
||||
lpos.z *= -1.0;
|
||||
var radius = getRadius(l.data.raw.strength);
|
||||
var radius = getRadius(l.strength);
|
||||
var minX = 0;
|
||||
var minY = 0;
|
||||
var minZ = 0;
|
||||
@ -552,10 +567,10 @@ class LightObject extends Object {
|
||||
lightsArray[i * 12 + 3] = 0.0; // padding or spot scale x
|
||||
|
||||
// light color
|
||||
var f = l.data.raw.strength;
|
||||
lightsArray[i * 12 + 4] = l.data.raw.color[0] * f;
|
||||
lightsArray[i * 12 + 5] = l.data.raw.color[1] * f;
|
||||
lightsArray[i * 12 + 6] = l.data.raw.color[2] * f;
|
||||
var f = l.strength;
|
||||
lightsArray[i * 12 + 4] = l.color.x * f;
|
||||
lightsArray[i * 12 + 5] = l.color.y * f;
|
||||
lightsArray[i * 12 + 6] = l.color.z * f;
|
||||
lightsArray[i * 12 + 7] = 0.0; // padding or spot scale y
|
||||
|
||||
// other data
|
||||
@ -566,13 +581,13 @@ class LightObject extends Object {
|
||||
|
||||
#if lnx_spot
|
||||
if (l.data.raw.type == "spot") {
|
||||
lightsArray[i * 12 + 9] = l.data.raw.spot_size;
|
||||
lightsArray[i * 12 + 9] = l.size;
|
||||
|
||||
var dir = l.look().normalize();
|
||||
lightsArraySpot[i * 8 ] = dir.x;
|
||||
lightsArraySpot[i * 8 + 1] = dir.y;
|
||||
lightsArraySpot[i * 8 + 2] = dir.z;
|
||||
lightsArraySpot[i * 8 + 3] = l.data.raw.spot_blend;
|
||||
lightsArraySpot[i * 8 + 3] = l.blend;
|
||||
|
||||
// Premultiply scale with z component
|
||||
var scale = l.transform.scale;
|
||||
|
||||
@ -28,13 +28,15 @@ class MeshObject extends Object {
|
||||
public var cameraList: Array<String> = null;
|
||||
public var screenSize = 0.0;
|
||||
public var frustumCulling = true;
|
||||
public var tilesheet: Tilesheet = null;
|
||||
public var activeTilesheet: Tilesheet = null;
|
||||
public var tilesheets: Array<Tilesheet> = null;
|
||||
public var skip_context: String = null; // Do not draw this context
|
||||
public var force_context: String = null; // Draw only this context
|
||||
static var lastPipeline: PipelineState = null;
|
||||
#if lnx_morph_target
|
||||
public var morphTarget: MorphTarget = null;
|
||||
#end
|
||||
public var vertexGroups: Map<String, Array<Vec4>> = null;
|
||||
|
||||
#if lnx_veloc
|
||||
public var prevMatrix = Mat4.identity();
|
||||
@ -50,6 +52,10 @@ class MeshObject extends Object {
|
||||
|
||||
public function setData(data: MeshData) {
|
||||
this.data = data;
|
||||
|
||||
if (this.materials != null && this.materials.length > 0)
|
||||
data.geom.instanceElements = @:privateAccess this.materials[0].shader.contexts[0].instanceElements;
|
||||
|
||||
data.refcount++;
|
||||
|
||||
#if (!lnx_batch)
|
||||
@ -87,7 +93,8 @@ class MeshObject extends Object {
|
||||
particleSystems = null;
|
||||
}
|
||||
#end
|
||||
if (tilesheet != null) tilesheet.remove();
|
||||
if (activeTilesheet != null) activeTilesheet.remove();
|
||||
if (tilesheets != null) { for (ts in tilesheets) { ts.remove(); } tilesheets = null; }
|
||||
if (Scene.active != null) Scene.active.meshes.remove(this);
|
||||
#if (rp_renderer == "Deferred")
|
||||
if (Scene.active != null) Scene.active.markMaterialParamsDirty();
|
||||
@ -126,12 +133,34 @@ class MeshObject extends Object {
|
||||
#end
|
||||
|
||||
public function setupTilesheet(tilesheetData: iron.data.SceneFormat.TTilesheetData) {
|
||||
tilesheet = new Tilesheet(tilesheetData, this);
|
||||
activeTilesheet = new Tilesheet(tilesheetData, this);
|
||||
if (tilesheets == null) tilesheets = new Array<Tilesheet>();
|
||||
tilesheets.push(activeTilesheet);
|
||||
}
|
||||
|
||||
public function setActiveTilesheet(tilesheetData: iron.data.SceneFormat.TTilesheetData, tilesheetActionRef: String = null) {
|
||||
var set = false;
|
||||
if (tilesheets != null) {
|
||||
for (ts in tilesheets) {
|
||||
if (ts.raw == tilesheetData) {
|
||||
if (activeTilesheet != null) activeTilesheet.pause();
|
||||
activeTilesheet = ts;
|
||||
if (tilesheetActionRef != null) activeTilesheet.play(tilesheetActionRef);
|
||||
set = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!set) {
|
||||
if (activeTilesheet != null) activeTilesheet.pause();
|
||||
setupTilesheet(tilesheetData);
|
||||
if (tilesheetActionRef != null) activeTilesheet.play(tilesheetActionRef);
|
||||
}
|
||||
}
|
||||
|
||||
public function setTilesheetAction(actionRef: String) {
|
||||
if (tilesheet != null) {
|
||||
tilesheet.play(actionRef);
|
||||
if (activeTilesheet != null) {
|
||||
activeTilesheet.play(actionRef);
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,6 +193,7 @@ class MeshObject extends Object {
|
||||
}
|
||||
|
||||
function cullMesh(context: String, camera: CameraObject, light: LightObject): Bool {
|
||||
var isShadow = context == "shadowmap";
|
||||
if (camera == null) return false;
|
||||
|
||||
if (camera.data.raw.frustum_culling && frustumCulling) {
|
||||
@ -172,11 +202,12 @@ class MeshObject extends Object {
|
||||
var radiusScale = data.isSkinned ? 2.0 : 1.0;
|
||||
#if lnx_gpu_particles
|
||||
// particleSystems for update, particleOwner for render
|
||||
if (particleSystems != null || particleOwner != null) radiusScale *= 1000;
|
||||
if (particleSystems != null && particleSystems.length > 0) return setCulled(isShadow, false);
|
||||
#end
|
||||
/*
|
||||
if (context == "voxel") radiusScale *= 100;
|
||||
if (data.geom.instanced) radiusScale *= 100;
|
||||
var isShadow = context == "shadowmap";
|
||||
if (data.geom.instanced) radiusScale *= 100;*/
|
||||
if (data.geom.instanced) return setCulled(isShadow, false);
|
||||
var frustumPlanes = isShadow ? light.frustumPlanes : camera.frustumPlanes;
|
||||
|
||||
if (isShadow && light.data.raw.type != "sun") { // Non-sun light bounds intersect camera frustum
|
||||
@ -191,8 +222,9 @@ class MeshObject extends Object {
|
||||
}
|
||||
}
|
||||
|
||||
culled = false;
|
||||
return culled;
|
||||
//culled = false;
|
||||
//return culled;
|
||||
return setCulled(isShadow, false);
|
||||
}
|
||||
|
||||
function skipContext(context: String, mat: MaterialData): Bool {
|
||||
@ -227,11 +259,6 @@ class MeshObject extends Object {
|
||||
if (cullMesh(context, Scene.active.camera, RenderPath.active.light)) return;
|
||||
var meshContext = raw != null ? context == "mesh" : false;
|
||||
|
||||
// Update tilesheet
|
||||
if (tilesheet != null && meshContext) {
|
||||
tilesheet.update();
|
||||
}
|
||||
|
||||
if (cameraList != null && cameraList.indexOf(Scene.active.camera.name) < 0) return;
|
||||
|
||||
#if lnx_gpu_particles
|
||||
|
||||
@ -61,6 +61,25 @@ class MorphTarget {
|
||||
public inline function setMorphValueDirect(index: Int, value: Float) {
|
||||
morphWeights.set(index, value);
|
||||
}
|
||||
|
||||
public function getMorphValue(name: String): Float {
|
||||
var i = morphMap.get(name);
|
||||
return (i != null) ? morphWeights.get(i) : 0.0;
|
||||
}
|
||||
|
||||
public function hasMorph(name: String): Bool {
|
||||
return morphMap.exists(name);
|
||||
}
|
||||
|
||||
public function resetWeights() {
|
||||
for (i in 0...morphWeights.length) {
|
||||
morphWeights.set(i, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
public function getMorphNames(): Array<String> {
|
||||
return [for (key in morphMap.keys()) key];
|
||||
}
|
||||
}
|
||||
|
||||
#end
|
||||
|
||||
@ -27,7 +27,6 @@ class Object {
|
||||
public var culled = false; // Object was culled last frame
|
||||
public var culledMesh = false;
|
||||
public var culledShadow = false;
|
||||
public var vertex_groups: Map<String, Array<Vec4>> = null;
|
||||
public var properties: Map<String, Dynamic> = null;
|
||||
var isEmpty = false;
|
||||
|
||||
@ -95,6 +94,7 @@ class Object {
|
||||
Removes the game object from the scene.
|
||||
**/
|
||||
public function remove() {
|
||||
Scene.active.removeFromGroups(this);
|
||||
if (isEmpty && Scene.active != null) Scene.active.empties.remove(this);
|
||||
if (animation != null) animation.remove();
|
||||
while (children.length > 0) children[0].remove();
|
||||
@ -111,16 +111,12 @@ class Object {
|
||||
@return Object or null
|
||||
**/
|
||||
public function getChild(name: String): Object {
|
||||
if (this.name == name) return this;
|
||||
else if (this.filename != "") {
|
||||
if (this.name == name + "_" + this.filename) return this;
|
||||
}
|
||||
|
||||
for (c in children) {
|
||||
if (c.name == name) return c;
|
||||
if (c.filename != "" && c.name == name + "_" + c.filename) return c;
|
||||
var r = c.getChild(name);
|
||||
if (r != null) return r;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -145,12 +141,10 @@ class Object {
|
||||
}
|
||||
|
||||
public function getChildOfType<T: Object>(type: Class<T>): T {
|
||||
if (Std.isOfType(this, type)) return cast this;
|
||||
else {
|
||||
for (c in children) {
|
||||
var r = c.getChildOfType(type);
|
||||
if (r != null) return r;
|
||||
}
|
||||
for (c in children) {
|
||||
if (Std.isOfType(c, type)) return cast c;
|
||||
var r = c.getChildOfType(type);
|
||||
if (r != null) return r;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import iron.data.SceneFormat;
|
||||
import iron.math.Quat;
|
||||
import iron.math.Vec3;
|
||||
import iron.math.Vec4;
|
||||
import iron.object.CurveObject;
|
||||
import iron.object.MeshObject;
|
||||
import iron.object.Object;
|
||||
import iron.system.Time;
|
||||
@ -19,6 +20,10 @@ import kha.arrays.Uint32Array;
|
||||
class ParticleSystemCPU {
|
||||
public var data: ParticleData;
|
||||
public var speed: FastFloat = 1.0; // Not used yet. Added to go in hand with `ParticleSystemGPU`
|
||||
public var curveGuides: Array<CurveObject> = [];
|
||||
public var curveGuideStrength: FastFloat = 1.0;
|
||||
public var curveGuideSpeed: FastFloat = 1.0;
|
||||
var paused: Bool = false;
|
||||
var r: TParticleData;
|
||||
|
||||
// Format
|
||||
@ -37,6 +42,7 @@ class ParticleSystemCPU {
|
||||
// Velocity
|
||||
var velocity: Vec3 = new Vec3(0.0, 0.0, 1.0); // object_align_factor: Float32Array
|
||||
var velocityRandom: FastFloat = 0.0; // factor_random
|
||||
var normalFactor: FastFloat = 0.0;
|
||||
|
||||
// Rotation
|
||||
var rotation: Bool = false; // use_rotations
|
||||
@ -114,11 +120,12 @@ class ParticleSystemCPU {
|
||||
scale = r.particle_size;
|
||||
scaleRandom = r.size_random;
|
||||
|
||||
velocity = new Vec3(r.object_align_factor[0], r.object_align_factor[1], r.object_align_factor[2]).mult(frameRate / baseFrameRate).mult(1 / scale);
|
||||
velocity = new Vec3(r.object_align_factor[0], r.object_align_factor[1], r.object_align_factor[2]).mult(frameRate / baseFrameRate);
|
||||
velocityRandom = r.factor_random * (frameRate / baseFrameRate);
|
||||
normalFactor = r.normal_factor * (frameRate / baseFrameRate);
|
||||
|
||||
if (Scene.active.raw.gravity != null) {
|
||||
gravity = new Vec3(Scene.active.raw.gravity[0], Scene.active.raw.gravity[1], Scene.active.raw.gravity[2]).mult(frameRate / baseFrameRate).mult(1 / scale);
|
||||
gravity = new Vec3(Scene.active.raw.gravity[0], Scene.active.raw.gravity[1], Scene.active.raw.gravity[2]).mult(frameRate / baseFrameRate);
|
||||
}
|
||||
gravityFactor = r.weight_gravity * (frameRate / baseFrameRate);
|
||||
textureFactor = r.weight_texture;
|
||||
@ -139,39 +146,36 @@ class ParticleSystemCPU {
|
||||
scaleElementsCount = getRampElementsLength();
|
||||
scaleRampSizeFactor = getRampSizeFactor();
|
||||
|
||||
switch (type) {
|
||||
case 0: // Emission
|
||||
loopAnim = {
|
||||
tick: function () {
|
||||
spawnTime += Time.delta * Time.scale;
|
||||
var expected: Int = Math.floor(spawnTime / spawnRate);
|
||||
while (spawnedParticles < expected && spawnedParticles < count) {
|
||||
spawnParticle();
|
||||
spawnedParticles++;
|
||||
}
|
||||
updateParticles();
|
||||
},
|
||||
target: null,
|
||||
props: null,
|
||||
duration: loop ? lifetimeSeconds : lifetimeSeconds * 2,
|
||||
done: function () {
|
||||
if (loop) start();
|
||||
}
|
||||
}
|
||||
|
||||
Scene.active.notifyOnInit(function () {
|
||||
if (autoStart) start();
|
||||
});
|
||||
case 1: // Hair
|
||||
Scene.active.notifyOnInit(function () {
|
||||
for (i in 0...count) spawnParticle();
|
||||
});
|
||||
default:
|
||||
}
|
||||
|
||||
Scene.active.notifyOnInit(function () {
|
||||
for (i in 0...count) addToPool();
|
||||
|
||||
switch (type) {
|
||||
case 0: // Emission
|
||||
loopAnim = {
|
||||
tick: function () {
|
||||
if (paused) return;
|
||||
spawnTime += Time.delta;
|
||||
var expected: Int = Math.floor(spawnTime / spawnRate);
|
||||
while (spawnedParticles < expected && spawnedParticles < count) {
|
||||
spawnParticle();
|
||||
spawnedParticles++;
|
||||
}
|
||||
updateParticles();
|
||||
},
|
||||
target: null,
|
||||
props: null,
|
||||
duration: loop ? lifetimeSeconds : lifetimeSeconds * 2,
|
||||
done: function () {
|
||||
if (loop) start();
|
||||
}
|
||||
}
|
||||
if (autoStart) start();
|
||||
case 1: // Hair
|
||||
for (i in 0...count) spawnParticle();
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -182,14 +186,12 @@ class ParticleSystemCPU {
|
||||
Tween.to(loopAnim);
|
||||
}
|
||||
|
||||
// TODO
|
||||
public function pause() {
|
||||
|
||||
paused = true;
|
||||
}
|
||||
|
||||
// TODO
|
||||
public function resume() {
|
||||
|
||||
paused = false;
|
||||
}
|
||||
|
||||
public function stop() {
|
||||
@ -246,6 +248,8 @@ class ParticleSystemCPU {
|
||||
var scalePos: FastFloat = owner.data.scalePos;
|
||||
var scalePosParticle: FastFloat = cast(o, MeshObject).data.scalePos;
|
||||
|
||||
var normDir: Vec3 = new Vec3();
|
||||
|
||||
// TODO: add all properties from Blender's UI
|
||||
switch (emitFrom) {
|
||||
case 0: // Vertices
|
||||
@ -253,6 +257,8 @@ class ParticleSystemCPU {
|
||||
var i: Int = Std.int(Math.random() * (pa.values.length / pa.size));
|
||||
var loc: Vec4 = new Vec4(pa.values[i * pa.size] * normFactor, pa.values[i * pa.size + 1] * normFactor, pa.values[i * pa.size + 2] * normFactor, 1);
|
||||
|
||||
if (normalFactor != 0.0) normDir = new Vec3(loc.x, loc.y, loc.z).normalize();
|
||||
|
||||
if (!localCoords) {
|
||||
loc.applyQuat(objectRot);
|
||||
loc.add(objectPos);
|
||||
@ -274,6 +280,9 @@ class ParticleSystemCPU {
|
||||
var pos: Vec3 = randomPointInTriangle(v0, v1, v2);
|
||||
|
||||
var loc: Vec4 = new Vec4(pos.x, pos.y, pos.z, 1).mult(normFactor);
|
||||
|
||||
if (normalFactor != 0.0) normDir = new Vec3(loc.x, loc.y, loc.z).normalize();
|
||||
|
||||
if (!localCoords) {
|
||||
loc.applyQuat(objectRot);
|
||||
loc.add(objectPos);
|
||||
@ -285,6 +294,8 @@ class ParticleSystemCPU {
|
||||
scaleFactorVolume.mult(0.5);
|
||||
var loc: Vec4 = new Vec4((Math.random() * 2.0 - 1.0) * scaleFactorVolume.x, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.y, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.z, 1);
|
||||
|
||||
if (normalFactor != 0.0) normDir = new Vec3(loc.x, loc.y, loc.z).normalize();
|
||||
|
||||
if (!localCoords) {
|
||||
loc.applyQuat(objectRot);
|
||||
loc.add(objectPos);
|
||||
@ -310,7 +321,9 @@ class ParticleSystemCPU {
|
||||
var randomZ: FastFloat = (Math.random() * 2 / (scale * particleScale) - 1 / (scale * particleScale)) * velocityRandom;
|
||||
var g: Vec3 = new Vec3();
|
||||
|
||||
var rotatedVelocity: Vec4 = new Vec4(velocity.x + randomX, velocity.y + randomY, velocity.z + randomZ, 1);
|
||||
if (normalFactor != 0.0) normDir = normDir.mult(normalFactor);
|
||||
|
||||
var rotatedVelocity: Vec4 = new Vec4(velocity.x + randomX + normDir.x, velocity.y + randomY + normDir.y, velocity.z + randomZ + normDir.z, 1);
|
||||
if (!localCoords) rotatedVelocity.applyQuat(objectRot);
|
||||
|
||||
if (rotation) {
|
||||
@ -371,7 +384,7 @@ class ParticleSystemCPU {
|
||||
|
||||
function updateParticles() {
|
||||
for (particle => physics in particlePhysics) {
|
||||
physics.age += Time.delta * Time.scale;
|
||||
physics.age += Time.delta;
|
||||
|
||||
if (physics.age >= physics.lifetime) {
|
||||
particlePhysics.remove(particle);
|
||||
@ -379,14 +392,63 @@ class ParticleSystemCPU {
|
||||
continue;
|
||||
}
|
||||
|
||||
physics.velocity.x += physics.gravity.x * Time.delta * Time.scale;
|
||||
physics.velocity.y += physics.gravity.y * Time.delta * Time.scale;
|
||||
physics.velocity.z += physics.gravity.z * Time.delta * Time.scale;
|
||||
physics.velocity.x += physics.gravity.x * Time.delta;
|
||||
physics.velocity.y += physics.gravity.y * Time.delta;
|
||||
physics.velocity.z += physics.gravity.z * Time.delta;
|
||||
|
||||
if (curveGuides != null && curveGuides.length > 0) {
|
||||
var curveVelX: FastFloat = 0.0;
|
||||
var curveVelY: FastFloat = 0.0;
|
||||
var curveVelZ: FastFloat = 0.0;
|
||||
var validCurves: Int = 0;
|
||||
|
||||
for (curve in curveGuides) {
|
||||
if (curve != null && curve.data != null && curve.data.splines != null && curve.splinesLength > 0) {
|
||||
var t = physics.age / physics.lifetime;
|
||||
|
||||
var tangent = curve.getTangent(t, 0);
|
||||
tangent.w = 0.0;
|
||||
tangent.applymat4(curve.transform.world);
|
||||
tangent.normalize();
|
||||
|
||||
var curveLen = curve.getLength(0);
|
||||
var speed = (curveLen / physics.lifetime) * curveGuideSpeed;
|
||||
|
||||
var tgtX = tangent.x * speed;
|
||||
var tgtY = tangent.y * speed;
|
||||
var tgtZ = tangent.z * speed;
|
||||
|
||||
if (localCoords) {
|
||||
var targetVel = new Vec4(tgtX, tgtY, tgtZ, 0.0);
|
||||
var invOwnerRot = new Quat(-owner.transform.rot.x, -owner.transform.rot.y, -owner.transform.rot.z, owner.transform.rot.w);
|
||||
targetVel.applyQuat(invOwnerRot);
|
||||
tgtX = targetVel.x;
|
||||
tgtY = targetVel.y;
|
||||
tgtZ = targetVel.z;
|
||||
}
|
||||
|
||||
curveVelX += tgtX;
|
||||
curveVelY += tgtY;
|
||||
curveVelZ += tgtZ;
|
||||
validCurves++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validCurves > 0) {
|
||||
curveVelX /= validCurves;
|
||||
curveVelY /= validCurves;
|
||||
curveVelZ /= validCurves;
|
||||
|
||||
physics.velocity.x += (curveVelX - physics.velocity.x) * curveGuideStrength;
|
||||
physics.velocity.y += (curveVelY - physics.velocity.y) * curveGuideStrength;
|
||||
physics.velocity.z += (curveVelZ - physics.velocity.z) * curveGuideStrength;
|
||||
}
|
||||
}
|
||||
|
||||
particle.transform.translate(
|
||||
physics.velocity.x * Time.delta * Time.scale,
|
||||
physics.velocity.y * Time.delta * Time.scale,
|
||||
physics.velocity.z * Time.delta * Time.scale
|
||||
physics.velocity.x * Time.delta,
|
||||
physics.velocity.y * Time.delta,
|
||||
physics.velocity.z * Time.delta
|
||||
);
|
||||
|
||||
if (rotation && dynamicRotation && orientationAxis == 3) setVelocityHair(particle, physics.velocity, randQuat, phaseQuat);
|
||||
|
||||
@ -141,10 +141,10 @@ class ParticleSystemGPU {
|
||||
dimx = object.transform.dim.x;
|
||||
dimy = object.transform.dim.y;
|
||||
|
||||
if (object.tilesheet != null) {
|
||||
tilesx = object.tilesheet.getTilesX();
|
||||
tilesy = object.tilesheet.getTilesY();
|
||||
tilesFramerate = object.tilesheet.action.framerate;
|
||||
if (object.activeTilesheet != null) {
|
||||
tilesx = object.activeTilesheet.getTilesX();
|
||||
tilesy = object.activeTilesheet.getTilesY();
|
||||
tilesFramerate = object.activeTilesheet.action.framerate;
|
||||
}
|
||||
|
||||
// Animate
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package iron.object;
|
||||
|
||||
import kha.FastFloat;
|
||||
import kha.Sound;
|
||||
import kha.audio1.AudioChannel;
|
||||
import iron.data.Data;
|
||||
import iron.data.SceneFormat;
|
||||
@ -13,9 +14,10 @@ class SpeakerObject extends Object {
|
||||
|
||||
public var data: TSpeakerData;
|
||||
public var paused(default, null) = false;
|
||||
public var sound(default, null): kha.Sound = null;
|
||||
public var sound(default, null): Sound = null;
|
||||
public var channels(default, null): Array<AudioChannel> = [];
|
||||
public var volume(default, null) : FastFloat;
|
||||
public var sampleRate(default, null) : Int;
|
||||
|
||||
public function new(data: TSpeakerData) {
|
||||
super();
|
||||
@ -26,28 +28,32 @@ class SpeakerObject extends Object {
|
||||
|
||||
if (data.sound == "") return;
|
||||
|
||||
Data.getSound(data.sound, function(sound: kha.Sound) {
|
||||
this.sound = sound;
|
||||
Data.getSound(data.sound, function(sound: Sound) {
|
||||
this.sound = cloneSound(sound);
|
||||
App.notifyOnInit(init);
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
sampleRate = sound.sampleRate;
|
||||
if (data.pitch != 1.0)
|
||||
sound.sampleRate = Std.int(sampleRate * data.pitch);
|
||||
if (visible && data.play_on_start) play();
|
||||
}
|
||||
|
||||
public function play() {
|
||||
if (sound == null || data.muted) return;
|
||||
public function play(): AudioChannel {
|
||||
if (sound == null || data.muted) return null;
|
||||
if (paused) {
|
||||
for (c in channels) c.play();
|
||||
paused = false;
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
var channel = Audio.play(sound, data.loop, data.stream);
|
||||
if (channel != null) {
|
||||
channels.push(channel);
|
||||
if (data.attenuation > 0 && channels.length == 1) App.notifyOnUpdate(update);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
public function pause() {
|
||||
@ -65,14 +71,24 @@ class SpeakerObject extends Object {
|
||||
|
||||
data.sound = sound;
|
||||
|
||||
Data.getSound(sound, function(sound: kha.Sound) {
|
||||
this.sound = sound;
|
||||
Data.getSound(sound, function(sound: Sound) {
|
||||
this.sound = cloneSound(sound);
|
||||
});
|
||||
|
||||
sampleRate = this.sound.sampleRate;
|
||||
if (data.pitch != 1.0)
|
||||
this.sound.sampleRate = Std.int(sampleRate * data.pitch);
|
||||
}
|
||||
|
||||
public function setVolume(volume: FastFloat) {
|
||||
data.volume = volume;
|
||||
}
|
||||
|
||||
public function setPosition(position: Float) {
|
||||
for (c in channels)
|
||||
if (position < c.length) c.position = position;
|
||||
}
|
||||
|
||||
function update() {
|
||||
if (paused) return;
|
||||
for (c in channels) if (c.finished) channels.remove(c);
|
||||
@ -103,6 +119,17 @@ class SpeakerObject extends Object {
|
||||
super.remove();
|
||||
}
|
||||
|
||||
function cloneSound(sound: Sound): Sound {
|
||||
if (sound == null) return null;
|
||||
var s = Type.createEmptyInstance(Sound);
|
||||
s.compressedData = sound.compressedData;
|
||||
s.uncompressedData = sound.uncompressedData;
|
||||
s.sampleRate = sound.sampleRate;
|
||||
s.length = sound.length;
|
||||
s.channels = sound.channels;
|
||||
return s;
|
||||
}
|
||||
|
||||
#end
|
||||
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
package iron.object;
|
||||
|
||||
import iron.App;
|
||||
import iron.Scene;
|
||||
import iron.data.SceneFormat;
|
||||
import iron.system.Time;
|
||||
import haxe.ds.Map;
|
||||
|
||||
|
||||
@:allow(iron.Scene)
|
||||
class Tilesheet {
|
||||
|
||||
public var tileX: Float = 0.0;
|
||||
@ -14,7 +15,8 @@ class Tilesheet {
|
||||
public var flipY: Bool = false;
|
||||
public var paused: Bool = false;
|
||||
public var frame: Int = 0;
|
||||
public var actions: Array<TTilesheetAction>;
|
||||
public var raw: TTilesheetData = null;
|
||||
public var actions: Array<TTilesheetAction> = null;
|
||||
public var action: TTilesheetAction = null;
|
||||
|
||||
public var ready: Bool = false;
|
||||
@ -31,8 +33,11 @@ class Tilesheet {
|
||||
|
||||
public function new(tilesheetData: TTilesheetData, ownerObject: MeshObject = null) {
|
||||
owner = ownerObject;
|
||||
raw = tilesheetData;
|
||||
actions = tilesheetData.actions;
|
||||
|
||||
Scene.active.tilesheets.push(this);
|
||||
|
||||
pendingAction = tilesheetData.start_action;
|
||||
if ((pendingAction == null || pendingAction == "") && actions.length > 0) {
|
||||
pendingAction = actions[0].name;
|
||||
@ -262,8 +267,10 @@ class Tilesheet {
|
||||
}
|
||||
|
||||
public function remove() {
|
||||
Scene.active.tilesheets.remove(this);
|
||||
ready = false;
|
||||
action = null;
|
||||
raw = null;
|
||||
actions = null;
|
||||
owner = null;
|
||||
currentMesh = null;
|
||||
|
||||
@ -106,6 +106,7 @@ class Transform {
|
||||
Rebuild the matrices, if needed.
|
||||
**/
|
||||
public function update() {
|
||||
if (object.constraints != null && object.constraints.length > 0) dirty = true;
|
||||
if (dirty) buildMatrix();
|
||||
}
|
||||
|
||||
@ -150,12 +151,19 @@ class Transform {
|
||||
if (boneParent != null) local.multmats(boneParent, local);
|
||||
|
||||
if (object.parent != null && !localOnly) {
|
||||
world.multmats3x4(local, object.parent.transform.world);
|
||||
// Swap multiplication order for linked objects to keep local transform intact
|
||||
var swapMult: Bool = object.raw != null && object.parent.raw != null && object.parent.raw.group_ref != null && object.parent.raw.group_ref != "";
|
||||
var a: Mat4 = swapMult ? object.parent.transform.world : local;
|
||||
var b: Mat4 = swapMult ? local : object.parent.transform.world;
|
||||
world.multmats3x4(a, b);
|
||||
}
|
||||
else {
|
||||
world.setFrom(local);
|
||||
}
|
||||
|
||||
// Constraints
|
||||
if (object.constraints != null) for (c in object.constraints) c.apply(this);
|
||||
|
||||
worldUnpack.setFrom(world);
|
||||
if (scaleWorld != 1.0) {
|
||||
worldUnpack._00 *= scaleWorld;
|
||||
@ -172,9 +180,6 @@ class Transform {
|
||||
worldUnpack._23 *= scaleWorld;
|
||||
}
|
||||
|
||||
// Constraints
|
||||
if (object.constraints != null) for (c in object.constraints) c.apply(this);
|
||||
|
||||
computeDim();
|
||||
|
||||
// Update children
|
||||
@ -265,7 +270,7 @@ class Transform {
|
||||
}
|
||||
|
||||
function computeRadius() {
|
||||
radius = Math.sqrt(dim.x * dim.x + dim.y * dim.y + dim.z * dim.z);
|
||||
radius = 0.5 * Math.sqrt(dim.x * dim.x + dim.y * dim.y + dim.z * dim.z);
|
||||
}
|
||||
|
||||
function computeDim() {
|
||||
|
||||
@ -428,12 +428,10 @@ class Uniforms {
|
||||
var v: Vec4 = null;
|
||||
helpVec.set(0, 0, 0, 0);
|
||||
switch (c.link) {
|
||||
#if lnx_debug
|
||||
case "_input": {
|
||||
helpVec.set(Input.getMouse().x / iron.App.w(), Input.getMouse().y / iron.App.h(), Input.getMouse().down() ? 1.0 : 0.0, 0.0);
|
||||
v = helpVec;
|
||||
}
|
||||
#end
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -690,7 +688,7 @@ class Uniforms {
|
||||
}
|
||||
case "_hosekSunDirection": {
|
||||
var w = Scene.active.world;
|
||||
if (w != null) {
|
||||
if (w != null && w.raw.sun_direction != null) {
|
||||
// Clamp Z for night cycle
|
||||
helpVec.set(w.raw.sun_direction[0],
|
||||
w.raw.sun_direction[1],
|
||||
@ -956,6 +954,22 @@ class Uniforms {
|
||||
}
|
||||
|
||||
static function setObjectConstant(g: Graphics, object: Object, location: ConstantLocation, c: TShaderConstant) {
|
||||
#if lnx_spot
|
||||
if (c.name == "LWVPSpot") {
|
||||
var light = getSpot(0);
|
||||
if (light != null) {
|
||||
if (object == null) helpMat.setIdentity();
|
||||
else helpMat.setFrom(object.transform.worldUnpack);
|
||||
|
||||
helpMat.multmat(light.VP);
|
||||
helpMat.multmat(biasMat);
|
||||
|
||||
g.setMatrix(location, helpMat.self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
if (c.link == null) return;
|
||||
|
||||
var camera = Scene.active.camera;
|
||||
@ -1263,17 +1277,17 @@ class Uniforms {
|
||||
var vy: Null<kha.FastFloat> = null;
|
||||
switch (c.link) {
|
||||
case "_tilesheetOffset": {
|
||||
var ts = cast(object, MeshObject).tilesheet;
|
||||
var ts = cast(object, MeshObject).activeTilesheet;
|
||||
vx = ts.tileX;
|
||||
vy = ts.tileY;
|
||||
}
|
||||
case "_tilesheetFlip": {
|
||||
var ts = cast(object, MeshObject).tilesheet;
|
||||
var ts = cast(object, MeshObject).activeTilesheet;
|
||||
vx = ts.flipX ? 1.0 : 0.0;
|
||||
vy = ts.flipY ? 1.0 : 0.0;
|
||||
}
|
||||
case "_tilesheetTiles": {
|
||||
var ts = cast(object, MeshObject).tilesheet;
|
||||
var ts = cast(object, MeshObject).activeTilesheet;
|
||||
vx = ts.getTilesX();
|
||||
vy = ts.getTilesY();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user