summaryrefslogtreecommitdiff
path: root/scene.cpp
blob: 53d06dd0444d51b1c13ddee00f3ce6f5ba7a9b46 (plain) (blame)
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
#include "camera.hpp"
#include "model.hpp"
#include "scene.hpp"

void update_scene(
	Model_Scene& ms,
	Device* dev,
	World& w
) {
	for (auto v : w.view<Transform, C_Model>()) {
		auto& t = v.get<Transform>();
		auto& m = v.get<C_Model>();
		m.i->transform = t.mat;
	}
	ms.update(dev);
}

std::pair<Entity_Id, int> scene_pick(
	World& world,
	const Camera& cam,
	int w,
	int h,
	int mx,
	int my
) {
	v2f uv = (2.0f * v2f(mx, my) - v2f(w, h)) / (float)h;
	v4f e =
		cam.get_proj().inverse() *
		v4f(uv.x, uv.y, -1.0f, 1.0f);
	e.z = -1.0f; e.w = 0.0f;
	v4f d4 = cam.get_view().inverse() * e;
	v3f d = v3f::normalised(v3f(d4.x, d4.y, d4.z));
	const v3f& o = cam.position;
	float t = INFINITY;
	Entity_Id r1 = 0;
	int r2 = -1;
	for (auto v : world.view<C_Model>()) {
		Model_Instance& inst = *v.get<C_Model>().i;
		Model* m = inst.m;
		int j;
		for (j = 0; j < m->mesh_count; j++) {
			AABB& b = inst.bounds[j];
			v3f id = 1.0f / d;
			v3f t1 = (b.min - o) * id;
			v3f t2 = (b.max - o) * id;
			float tmin = std::max(std::max(
				std::min(t1.x, t2.x),
				std::min(t1.y, t2.y)),
				std::min(t1.z, t2.z)
			);
			float tmax = std::min(std::min(
				std::max(t1.x, t2.x),
				std::max(t1.y, t2.y)),
				std::max(t1.z, t2.z)
			);
			if (tmax < 0.0f || tmin > tmax)
				continue;
			if (tmin < t) {
				t = tmin;
				r1 = v.entity();
				r2 = j;
			}
		}
	}
	return { r1, r2 };
}