forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			206 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			206 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package iron.object;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import kha.graphics4.Graphics;
							 | 
						||
| 
								 | 
							
								import kha.graphics4.TextureFormat;
							 | 
						||
| 
								 | 
							
								import kha.graphics4.DepthStencilFormat;
							 | 
						||
| 
								 | 
							
								import kha.graphics4.CubeMap;
							 | 
						||
| 
								 | 
							
								import iron.data.ProbeData;
							 | 
						||
| 
								 | 
							
								import iron.data.CameraData;
							 | 
						||
| 
								 | 
							
								import iron.data.SceneFormat;
							 | 
						||
| 
								 | 
							
								import iron.math.Vec4;
							 | 
						||
| 
								 | 
							
								import iron.math.Mat4;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ProbeObject extends Object {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if rp_probes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public var data: ProbeData;
							 | 
						||
| 
								 | 
							
									public var renderTarget: kha.Image = null;
							 | 
						||
| 
								 | 
							
									public var camera: CameraObject = null;
							 | 
						||
| 
								 | 
							
									public var ready = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Cubemap update
							 | 
						||
| 
								 | 
							
									public var perFrame = false; // Update probe every frame
							 | 
						||
| 
								 | 
							
									public var redraw = true; // Update probe next frame
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var m1: Mat4;
							 | 
						||
| 
								 | 
							
									var m2: Mat4;
							 | 
						||
| 
								 | 
							
									var proben: Vec4;
							 | 
						||
| 
								 | 
							
									var probep: Vec4;
							 | 
						||
| 
								 | 
							
									// static var v = new Vec4();
							 | 
						||
| 
								 | 
							
									static var p = new Vec4();
							 | 
						||
| 
								 | 
							
									static var q = new Vec4();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function new(data: ProbeData) {
							 | 
						||
| 
								 | 
							
										super();
							 | 
						||
| 
								 | 
							
										this.data = data;
							 | 
						||
| 
								 | 
							
										Scene.active.probes.push(this);
							 | 
						||
| 
								 | 
							
										iron.App.notifyOnInit(init);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function remove() {
							 | 
						||
| 
								 | 
							
										if (Scene.active != null) Scene.active.probes.remove(this);
							 | 
						||
| 
								 | 
							
										// if (camera != null) camera.remove();
							 | 
						||
| 
								 | 
							
										super.remove();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function init() {
							 | 
						||
| 
								 | 
							
										probep = transform.world.getLoc();
							 | 
						||
| 
								 | 
							
										proben = transform.up().normalize();
							 | 
						||
| 
								 | 
							
										proben.w = -probep.dot(proben);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (data.raw.type == "planar") {
							 | 
						||
| 
								 | 
							
											m1 = Mat4.identity();
							 | 
						||
| 
								 | 
							
											m2 = Mat4.identity();
							 | 
						||
| 
								 | 
							
											reflect(m1, proben, probep);
							 | 
						||
| 
								 | 
							
											reflect(m2, new Vec4(0, 1, 0), probep);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											transform.scale.z = 1.0; // Only take dim.z into account
							 | 
						||
| 
								 | 
							
											transform.buildMatrix();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// var aspect = transform.scale.x / transform.scale.y;
							 | 
						||
| 
								 | 
							
											var aspect = iron.App.w() / iron.App.h(); // TODO
							 | 
						||
| 
								 | 
							
											var craw: TCameraData = {
							 | 
						||
| 
								 | 
							
												name: raw.name + "_Camera",
							 | 
						||
| 
								 | 
							
												near_plane: Scene.active.camera.data.raw.near_plane,
							 | 
						||
| 
								 | 
							
												far_plane: Scene.active.camera.data.raw.far_plane,
							 | 
						||
| 
								 | 
							
												fov: Scene.active.camera.data.raw.fov,
							 | 
						||
| 
								 | 
							
												aspect: aspect
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
											new CameraData(craw, function(cdata: CameraData) {
							 | 
						||
| 
								 | 
							
												camera = new CameraObject(cdata);
							 | 
						||
| 
								 | 
							
												camera.renderTarget = kha.Image.createRenderTarget(
							 | 
						||
| 
								 | 
							
													iron.App.w(), // TODO
							 | 
						||
| 
								 | 
							
													iron.App.h(),
							 | 
						||
| 
								 | 
							
													TextureFormat.RGBA32,
							 | 
						||
| 
								 | 
							
													DepthStencilFormat.NoDepthAndStencil
							 | 
						||
| 
								 | 
							
												);
							 | 
						||
| 
								 | 
							
												camera.name = craw.name;
							 | 
						||
| 
								 | 
							
												camera.setParent(iron.Scene.active.root);
							 | 
						||
| 
								 | 
							
												// Make target bindable from render path
							 | 
						||
| 
								 | 
							
												var rt = new RenderPath.RenderTarget(new RenderPath.RenderTargetRaw());
							 | 
						||
| 
								 | 
							
												rt.raw.name = raw.name;
							 | 
						||
| 
								 | 
							
												rt.image = camera.renderTarget;
							 | 
						||
| 
								 | 
							
												RenderPath.active.renderTargets.set(rt.raw.name, rt);
							 | 
						||
| 
								 | 
							
												ready = true;
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if (data.raw.type == "cubemap") {
							 | 
						||
| 
								 | 
							
											transform.scale.x *= transform.dim.x;
							 | 
						||
| 
								 | 
							
											transform.scale.y *= transform.dim.y;
							 | 
						||
| 
								 | 
							
											transform.scale.z *= transform.dim.z;
							 | 
						||
| 
								 | 
							
											transform.buildMatrix();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var craw: TCameraData = {
							 | 
						||
| 
								 | 
							
												name: data.raw.name + "_Camera",
							 | 
						||
| 
								 | 
							
												near_plane: Scene.active.camera.data.raw.near_plane,
							 | 
						||
| 
								 | 
							
												far_plane: Scene.active.camera.data.raw.far_plane,
							 | 
						||
| 
								 | 
							
												fov: 1.5708, // pi/2
							 | 
						||
| 
								 | 
							
												aspect: 1.0
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
											new CameraData(craw, function(cdata: CameraData) {
							 | 
						||
| 
								 | 
							
												camera = new CameraObject(cdata);
							 | 
						||
| 
								 | 
							
												camera.renderTargetCube = CubeMap.createRenderTarget(
							 | 
						||
| 
								 | 
							
													1024, // TODO
							 | 
						||
| 
								 | 
							
													TextureFormat.RGBA32,
							 | 
						||
| 
								 | 
							
													DepthStencilFormat.NoDepthAndStencil
							 | 
						||
| 
								 | 
							
												);
							 | 
						||
| 
								 | 
							
												camera.name = craw.name;
							 | 
						||
| 
								 | 
							
												camera.setParent(iron.Scene.active.root);
							 | 
						||
| 
								 | 
							
												// Make target bindable from render path
							 | 
						||
| 
								 | 
							
												var rt = new RenderPath.RenderTarget(new RenderPath.RenderTargetRaw());
							 | 
						||
| 
								 | 
							
												rt.raw.name = raw.name;
							 | 
						||
| 
								 | 
							
												rt.raw.is_cubemap = true;
							 | 
						||
| 
								 | 
							
												rt.isCubeMap = true;
							 | 
						||
| 
								 | 
							
												rt.cubeMap = camera.renderTargetCube;
							 | 
						||
| 
								 | 
							
												RenderPath.active.renderTargets.set(rt.raw.name, rt);
							 | 
						||
| 
								 | 
							
												ready = true;
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static function reflect(m: Mat4, n: Vec4, p: Vec4) {
							 | 
						||
| 
								 | 
							
										var c = -p.dot(n);
							 | 
						||
| 
								 | 
							
										m._00 = 1 - 2 * n.x * n.x;
							 | 
						||
| 
								 | 
							
										m._10 =   - 2 * n.x * n.y;
							 | 
						||
| 
								 | 
							
										m._20 =   - 2 * n.x * n.z;
							 | 
						||
| 
								 | 
							
										m._30 =   - 2 * n.x * c;
							 | 
						||
| 
								 | 
							
										m._01 =   - 2 * n.x * n.y;
							 | 
						||
| 
								 | 
							
										m._11 = 1 - 2 * n.y * n.y;
							 | 
						||
| 
								 | 
							
										m._21 =   - 2 * n.y * n.z;
							 | 
						||
| 
								 | 
							
										m._31 =   - 2 * n.y * c;
							 | 
						||
| 
								 | 
							
										m._02 =   - 2 * n.x * n.z;
							 | 
						||
| 
								 | 
							
										m._12 =   - 2 * n.y * n.z;
							 | 
						||
| 
								 | 
							
										m._22 = 1 - 2 * n.z * n.z;
							 | 
						||
| 
								 | 
							
										m._32 =   - 2 * n.z * c;
							 | 
						||
| 
								 | 
							
										m._03 = 0;
							 | 
						||
| 
								 | 
							
										m._13 = 0;
							 | 
						||
| 
								 | 
							
										m._23 = 0;
							 | 
						||
| 
								 | 
							
										m._33 = 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static inline function sign(f: Float): Float {
							 | 
						||
| 
								 | 
							
										return f > 0.0 ? 1.0 : f < 0.0 ? -1.0 : 0.0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static function obliqueProjection(m: Mat4, plane: Vec4) {
							 | 
						||
| 
								 | 
							
										// http://www.terathon.com/code/oblique.html
							 | 
						||
| 
								 | 
							
										p.x = (sign(plane.x) + m._20) / m._00;
							 | 
						||
| 
								 | 
							
										p.y = (sign(plane.y) + m._21) / m._11;
							 | 
						||
| 
								 | 
							
										p.z = -1.0;
							 | 
						||
| 
								 | 
							
										p.w = (1.0 + m._22) / m._32;
							 | 
						||
| 
								 | 
							
										q.setFrom(plane).mult(2.0 / plane.dot(p));
							 | 
						||
| 
								 | 
							
										m._02 = q.x;
							 | 
						||
| 
								 | 
							
										m._12 = q.y;
							 | 
						||
| 
								 | 
							
										m._22 = q.z + 1.0;
							 | 
						||
| 
								 | 
							
										m._32 = q.w;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function cullProbe(camera: CameraObject): Bool {
							 | 
						||
| 
								 | 
							
										if (camera.data.raw.frustum_culling) {
							 | 
						||
| 
								 | 
							
											if (!CameraObject.sphereInFrustum(camera.frustumPlanes, transform, 1.0)) {
							 | 
						||
| 
								 | 
							
												culled = true;
							 | 
						||
| 
								 | 
							
												return culled;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										culled = false;
							 | 
						||
| 
								 | 
							
										return culled;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function render(g: Graphics, activeCamera: CameraObject) {
							 | 
						||
| 
								 | 
							
										if (camera == null || !ready || !RenderPath.active.ready || !visible || cullProbe(activeCamera)) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (data.raw.type == "planar") {
							 | 
						||
| 
								 | 
							
											camera.V.setFrom(m1);
							 | 
						||
| 
								 | 
							
											camera.V.multmat(activeCamera.V);
							 | 
						||
| 
								 | 
							
											camera.V.multmat(m2);
							 | 
						||
| 
								 | 
							
											camera.transform.local.getInverse(camera.V);
							 | 
						||
| 
								 | 
							
											camera.transform.decompose();
							 | 
						||
| 
								 | 
							
											// Skip objects below the reflection plane
							 | 
						||
| 
								 | 
							
											// v.setFrom(proben).applyproj(camera.V);
							 | 
						||
| 
								 | 
							
											// obliqueProjection(#if (lnx_taa) camera.noJitterP #else camera.P #end, v);
							 | 
						||
| 
								 | 
							
											camera.renderFrame(g);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if (data.raw.type == "cubemap") {
							 | 
						||
| 
								 | 
							
											if (perFrame || redraw) {
							 | 
						||
| 
								 | 
							
												for (i in 0...6) {
							 | 
						||
| 
								 | 
							
													camera.currentFace = i;
							 | 
						||
| 
								 | 
							
													#if (!kha_opengl && !kha_webgl)
							 | 
						||
| 
								 | 
							
													var flip = (i == 2 || i == 3) ? true : false; // Flip +Y, -Y
							 | 
						||
| 
								 | 
							
													#else
							 | 
						||
| 
								 | 
							
													var flip = false;
							 | 
						||
| 
								 | 
							
													#end
							 | 
						||
| 
								 | 
							
													CameraObject.setCubeFace(camera.V, probep, i, flip);
							 | 
						||
| 
								 | 
							
													camera.transform.local.getInverse(camera.V);
							 | 
						||
| 
								 | 
							
													camera.transform.decompose();
							 | 
						||
| 
								 | 
							
													camera.renderFrame(g);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										redraw = false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#end
							 | 
						||
| 
								 | 
							
								}
							 |