summaryrefslogtreecommitdiff
path: root/Runtime/Camera/LightProbes.h
blob: cd59f9bd8b99a593ce92d9c77a1c9ca5a17a09d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#pragma once

#include "Runtime/BaseClasses/NamedObject.h"
#include "Runtime/Utilities/dynamic_array.h"
#include "Runtime/Math/Vector3.h"
#include "Runtime/Math/Vector4.h"
#include "Runtime/Math/Matrix3x3.h"

class Renderer;

// column-major
// m0   m3   m6   m9	
// m1   m4   m7   m10
// m2   m5   m8   m11
// So far only used for light probes, move it to Matrix3x4f.h if it ever grows beyond that
class Matrix3x4f
{
public:
	float m_Data[12];
	///@todo: Can't be Transfer optimized because Transfer doesn't write the same as memory layout
	DECLARE_SERIALIZE_NO_PPTR (Matrix3x4f)
	Matrix3x4f () {}
	Matrix3x4f (const Matrix3x3f& other);
	float& operator [] (int index) { return m_Data[index];}
	Vector3f MultiplyVector3 (const Vector3f& v) const;
	Vector3f MultiplyPoint3 (const Vector3f& v) const;
};

enum { kLightProbeBasisCount = 9};
enum { kLightProbeCoefficientCount = kLightProbeBasisCount*3};

struct LightProbeCoefficients
{
	float sh[kLightProbeBasisCount*3];
	float& operator [] (int i) { return sh[i]; }
	DECLARE_SERIALIZE(LightmapData)
};

struct Tetrahedron
{
	int indices[4];
	int neighbors[4];
	// For an inner tetrahedron: the matrix is the cached inverted matrix used for calculating barycentric coordinates
	// For an outer tetrahedron: it's a matrix allowing the calculation of the cubic coefficients for the
	// t parameter polynomial, used for calculating barycentric coordinates as well
	Matrix3x4f matrix;
	DECLARE_SERIALIZE(Tetrahedron)
};

struct LightProbeData
{
	dynamic_array<Vector3f> positions;
	dynamic_array<LightProbeCoefficients> coefficients;
	dynamic_array<Tetrahedron> tetrahedra;
	// TODO: Sort probes so that all outer probes are at the beginning of m_BakedPositions. Thanks to that m_HullRays will be only 
	// as long as there are outer probes, not all probes.
	dynamic_array<Vector3f> hullRays;
};

class LightProbes;
LightProbes* GetLightProbes ();

class LightProbes : public NamedObject
{
public:
	REGISTER_DERIVED_CLASS (LightProbes, NamedObject)
	DECLARE_OBJECT_SERIALIZE(LightProbes)

	LightProbes(MemLabelId label, ObjectCreationMode mode);

	void AwakeFromLoad(AwakeFromLoadMode mode);
	Vector3f* GetPositions() { return m_Data.positions.size() > 0 ? &m_Data.positions[0] : NULL; }
	int GetPositionsSize() { return m_Data.positions.size(); }
	LightProbeCoefficients* GetCoefficients() { return m_Data.coefficients.size() > 0 ? &m_Data.coefficients[0] : NULL; }
	void SetCoefficients( float* data, int size );
	int GetTetrahedraSize() { return m_Data.tetrahedra.size();}
#if UNITY_EDITOR
	Tetrahedron* GetTetrahedra() { return m_Data.tetrahedra.size() > 0 ? &m_Data.tetrahedra[0] : NULL;}
	Vector3f* GetHullRays() { return m_Data.hullRays.size() > 0 ? &m_Data.hullRays[0] : NULL; }
	void SetBakedData (const dynamic_array<Vector3f>& positions, const dynamic_array<LightProbeCoefficients>& coefficents);
#endif
	inline void GetInterpolatedLightProbe(const Vector3f& position, Renderer* renderer, float* coefficients)
	{
		int tetIndex = -1;
		Vector4f weights;
		float t;
		GetInterpolatedLightProbe(position, renderer, coefficients, tetIndex, weights, t);
	}
	void GetInterpolatedLightProbe(const Vector3f& position, Renderer* renderer, float* coefficients, int& tetIndex, Vector4f& weights, float& t);

	static void InitializeClass() {}
	static void CleanupClass() {}
	inline static bool AreBaked() { LightProbes* lp = GetLightProbes(); return lp && lp->GetTetrahedraSize() > 0; }

private:
	LightProbeData m_Data;
};