File: lab_cameras.cpp

package info (click to toggle)
freespace2 25.0.0~rc11%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 47,232 kB
  • sloc: cpp: 657,500; ansic: 22,305; sh: 293; python: 200; makefile: 198; xml: 181
file content (88 lines) | stat: -rw-r--r-- 2,384 bytes parent folder | download
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
#include "globalincs/pstypes.h"
#include "io/key.h"
#include "lab/renderer/lab_cameras.h"
#include "lab/labv2_internal.h"


LabCamera::~LabCamera() {
	cam_delete(FS_camera);
}

void OrbitCamera::handleInput(int dx, int dy, bool, bool rmbDown, int modifierKeys) {
	if (dx == 0 && dy == 0)
		return;

	if (rmbDown) {
		if (modifierKeys & KEY_SHIFTED) {
			distance *= 1.0f + (dy / 200.0f);
			CLAMP(distance, 1.0f, 10000000.0f);
		}
		else {
			theta += dx / 100.0f;
			phi += dy / 100.0f;

			CLAMP(phi, 0.01f, PI - 0.01f);
		}
	}

	updateCamera();
}

void OrbitCamera::displayedObjectChanged() {
	float distance_multiplier = 1.6f;

	if (getLabManager()->CurrentObject != -1) {
		object* obj = &Objects[getLabManager()->CurrentObject];
		
		// Ships and Missiles use the object radius to get a camera distance
		distance = obj->radius * distance_multiplier;

		// Beams use the muzzle radius
		if (obj->type == OBJ_BEAM) {
			weapon_info* wip = &Weapon_info[Beams[obj->instance].weapon_info_index];
			if (wip != nullptr) {
				distance = wip->b_info.beam_muzzle_radius * distance_multiplier;
			}
		// Lasers use the laser length
		} else if (obj->type == OBJ_WEAPON) {
			weapon_info* wip = &Weapon_info[Weapons[obj->instance].weapon_info_index];
			if (wip != nullptr && wip->render_type == WRT_LASER) {
				distance = wip->laser_length * distance_multiplier;
			}
		}
	}

	updateCamera();
}

void OrbitCamera::updateCamera() {
	auto cam = FS_camera.getCamera();
	vec3d new_position;
	new_position.xyz.x = sinf(phi) * cosf(theta);
	new_position.xyz.y = cosf(phi);
	new_position.xyz.z = sinf(phi) * sinf(theta);

	vm_vec_scale(&new_position, distance);

	object* obj = &Objects[getLabManager()->CurrentObject];
	vec3d target = obj->pos;

	if (obj->type == OBJ_WEAPON) {
		weapon_info* wip = &Weapon_info[Weapons[obj->instance].weapon_info_index];
		if (wip != nullptr && wip->render_type == WRT_LASER) {
			// Offset target by half the laser length forward along the facing
			vec3d forward;
			vm_vec_copy_normalize(&forward, &obj->orient.vec.fvec);
			vm_vec_scale_add2(&target, &forward, wip->laser_length * 0.5f);
		}
		
		vm_vec_add2(&new_position, &target);
	}

	cam->set_position(&new_position);

	// If these are the same then that's not great so do nothing and use the last facing value
	if (!vm_vec_same(&new_position, &target)) {
		cam->set_rotation_facing(&target);
	}
}