1 /*************************************************************************/
2 /*  arvr_interface_gdnative.cpp                                          */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #include "arvr_interface_gdnative.h"
32 #include "main/input_default.h"
33 #include "servers/arvr/arvr_positional_tracker.h"
34 #include "servers/visual/visual_server_globals.h"
35 
_bind_methods()36 void ARVRInterfaceGDNative::_bind_methods() {
37 	ADD_PROPERTY_DEFAULT("interface_is_initialized", false);
38 	ADD_PROPERTY_DEFAULT("ar_is_anchor_detection_enabled", false);
39 }
40 
ARVRInterfaceGDNative()41 ARVRInterfaceGDNative::ARVRInterfaceGDNative() {
42 	print_verbose("Construct gdnative interface\n");
43 
44 	// we won't have our data pointer until our library gets set
45 	data = NULL;
46 
47 	interface = NULL;
48 }
49 
~ARVRInterfaceGDNative()50 ARVRInterfaceGDNative::~ARVRInterfaceGDNative() {
51 	print_verbose("Destruct gdnative interface\n");
52 
53 	if (interface != NULL && is_initialized()) {
54 		uninitialize();
55 	};
56 
57 	// cleanup after ourselves
58 	cleanup();
59 }
60 
cleanup()61 void ARVRInterfaceGDNative::cleanup() {
62 	if (interface != NULL) {
63 		interface->destructor(data);
64 		data = NULL;
65 		interface = NULL;
66 	}
67 }
68 
set_interface(const godot_arvr_interface_gdnative * p_interface)69 void ARVRInterfaceGDNative::set_interface(const godot_arvr_interface_gdnative *p_interface) {
70 	// this should only be called once, just being paranoid..
71 	if (interface) {
72 		cleanup();
73 	}
74 
75 	// bind to our interface
76 	interface = p_interface;
77 
78 	// Now we do our constructing...
79 	data = interface->constructor((godot_object *)this);
80 }
81 
get_name() const82 StringName ARVRInterfaceGDNative::get_name() const {
83 
84 	ERR_FAIL_COND_V(interface == NULL, StringName());
85 
86 	godot_string result = interface->get_name(data);
87 
88 	StringName name = *(String *)&result;
89 
90 	godot_string_destroy(&result);
91 
92 	return name;
93 }
94 
get_capabilities() const95 int ARVRInterfaceGDNative::get_capabilities() const {
96 	int capabilities;
97 
98 	ERR_FAIL_COND_V(interface == NULL, 0); // 0 = None
99 
100 	capabilities = interface->get_capabilities(data);
101 
102 	return capabilities;
103 }
104 
get_anchor_detection_is_enabled() const105 bool ARVRInterfaceGDNative::get_anchor_detection_is_enabled() const {
106 
107 	ERR_FAIL_COND_V(interface == NULL, false);
108 
109 	return interface->get_anchor_detection_is_enabled(data);
110 }
111 
set_anchor_detection_is_enabled(bool p_enable)112 void ARVRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) {
113 
114 	ERR_FAIL_COND(interface == NULL);
115 
116 	interface->set_anchor_detection_is_enabled(data, p_enable);
117 }
118 
get_camera_feed_id()119 int ARVRInterfaceGDNative::get_camera_feed_id() {
120 
121 	ERR_FAIL_COND_V(interface == NULL, 0);
122 
123 	if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) {
124 		return (unsigned int)interface->get_camera_feed_id(data);
125 	} else {
126 		return 0;
127 	}
128 }
129 
is_stereo()130 bool ARVRInterfaceGDNative::is_stereo() {
131 	bool stereo;
132 
133 	ERR_FAIL_COND_V(interface == NULL, false);
134 
135 	stereo = interface->is_stereo(data);
136 
137 	return stereo;
138 }
139 
is_initialized() const140 bool ARVRInterfaceGDNative::is_initialized() const {
141 
142 	ERR_FAIL_COND_V(interface == NULL, false);
143 
144 	return interface->is_initialized(data);
145 }
146 
initialize()147 bool ARVRInterfaceGDNative::initialize() {
148 	ERR_FAIL_COND_V(interface == NULL, false);
149 
150 	bool initialized = interface->initialize(data);
151 
152 	if (initialized) {
153 		// if we successfully initialize our interface and we don't have a primary interface yet, this becomes our primary interface
154 
155 		ARVRServer *arvr_server = ARVRServer::get_singleton();
156 		if ((arvr_server != NULL) && (arvr_server->get_primary_interface() == NULL)) {
157 			arvr_server->set_primary_interface(this);
158 		};
159 	};
160 
161 	return initialized;
162 }
163 
uninitialize()164 void ARVRInterfaceGDNative::uninitialize() {
165 	ERR_FAIL_COND(interface == NULL);
166 
167 	ARVRServer *arvr_server = ARVRServer::get_singleton();
168 	if (arvr_server != NULL) {
169 		// Whatever happens, make sure this is no longer our primary interface
170 		arvr_server->clear_primary_interface_if(this);
171 	}
172 
173 	interface->uninitialize(data);
174 }
175 
get_render_targetsize()176 Size2 ARVRInterfaceGDNative::get_render_targetsize() {
177 
178 	ERR_FAIL_COND_V(interface == NULL, Size2());
179 
180 	godot_vector2 result = interface->get_render_targetsize(data);
181 	Vector2 *vec = (Vector2 *)&result;
182 
183 	return *vec;
184 }
185 
get_transform_for_eye(ARVRInterface::Eyes p_eye,const Transform & p_cam_transform)186 Transform ARVRInterfaceGDNative::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) {
187 	Transform *ret;
188 
189 	ERR_FAIL_COND_V(interface == NULL, Transform());
190 
191 	godot_transform t = interface->get_transform_for_eye(data, (int)p_eye, (godot_transform *)&p_cam_transform);
192 
193 	ret = (Transform *)&t;
194 
195 	return *ret;
196 }
197 
get_projection_for_eye(ARVRInterface::Eyes p_eye,real_t p_aspect,real_t p_z_near,real_t p_z_far)198 CameraMatrix ARVRInterfaceGDNative::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
199 	CameraMatrix cm;
200 
201 	ERR_FAIL_COND_V(interface == NULL, CameraMatrix());
202 
203 	interface->fill_projection_for_eye(data, (godot_real *)cm.matrix, (godot_int)p_eye, p_aspect, p_z_near, p_z_far);
204 
205 	return cm;
206 }
207 
get_external_texture_for_eye(ARVRInterface::Eyes p_eye)208 unsigned int ARVRInterfaceGDNative::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) {
209 
210 	ERR_FAIL_COND_V(interface == NULL, 0);
211 
212 	if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) {
213 		return (unsigned int)interface->get_external_texture_for_eye(data, (godot_int)p_eye);
214 	} else {
215 		return 0;
216 	}
217 }
218 
commit_for_eye(ARVRInterface::Eyes p_eye,RID p_render_target,const Rect2 & p_screen_rect)219 void ARVRInterfaceGDNative::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
220 
221 	ERR_FAIL_COND(interface == NULL);
222 
223 	interface->commit_for_eye(data, (godot_int)p_eye, (godot_rid *)&p_render_target, (godot_rect2 *)&p_screen_rect);
224 }
225 
process()226 void ARVRInterfaceGDNative::process() {
227 	ERR_FAIL_COND(interface == NULL);
228 
229 	interface->process(data);
230 }
231 
notification(int p_what)232 void ARVRInterfaceGDNative::notification(int p_what) {
233 	ERR_FAIL_COND(interface == NULL);
234 
235 	// this is only available in interfaces that implement 1.1 or later
236 	if ((interface->version.major > 1) || ((interface->version.major == 1) && (interface->version.minor > 0))) {
237 		interface->notification(data, p_what);
238 	}
239 }
240 
241 /////////////////////////////////////////////////////////////////////////////////////
242 // some helper callbacks
243 
244 extern "C" {
245 
godot_arvr_register_interface(const godot_arvr_interface_gdnative * p_interface)246 void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface) {
247 	// If our major version is 0 or bigger then 10, we're likely looking at our constructor pointer from an older plugin
248 	ERR_FAIL_COND_MSG((p_interface->version.major == 0) || (p_interface->version.major > 10), "GDNative ARVR interfaces build for Godot 3.0 are not supported.");
249 
250 	Ref<ARVRInterfaceGDNative> new_interface;
251 	new_interface.instance();
252 	new_interface->set_interface((const godot_arvr_interface_gdnative *)p_interface);
253 	ARVRServer::get_singleton()->add_interface(new_interface);
254 }
255 
godot_arvr_get_worldscale()256 godot_real GDAPI godot_arvr_get_worldscale() {
257 	ARVRServer *arvr_server = ARVRServer::get_singleton();
258 	ERR_FAIL_NULL_V(arvr_server, 1.0);
259 
260 	return arvr_server->get_world_scale();
261 }
262 
godot_arvr_get_reference_frame()263 godot_transform GDAPI godot_arvr_get_reference_frame() {
264 	godot_transform reference_frame;
265 	Transform *reference_frame_ptr = (Transform *)&reference_frame;
266 
267 	ARVRServer *arvr_server = ARVRServer::get_singleton();
268 	if (arvr_server != NULL) {
269 		*reference_frame_ptr = arvr_server->get_reference_frame();
270 	} else {
271 		godot_transform_new_identity(&reference_frame);
272 	}
273 
274 	return reference_frame;
275 }
276 
godot_arvr_blit(godot_int p_eye,godot_rid * p_render_target,godot_rect2 * p_rect)277 void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect) {
278 	// blits out our texture as is, handy for preview display of one of the eyes that is already rendered with lens distortion on an external HMD
279 	ARVRInterface::Eyes eye = (ARVRInterface::Eyes)p_eye;
280 	RID *render_target = (RID *)p_render_target;
281 	Rect2 screen_rect = *(Rect2 *)p_rect;
282 
283 	if (eye == ARVRInterface::EYE_LEFT) {
284 		screen_rect.size.x /= 2.0;
285 	} else if (p_eye == ARVRInterface::EYE_RIGHT) {
286 		screen_rect.size.x /= 2.0;
287 		screen_rect.position.x += screen_rect.size.x;
288 	}
289 
290 	VSG::rasterizer->set_current_render_target(RID());
291 	VSG::rasterizer->blit_render_target_to_screen(*render_target, screen_rect, 0);
292 }
293 
godot_arvr_get_texid(godot_rid * p_render_target)294 godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target) {
295 	// In order to send off our textures to display on our hardware we need the opengl texture ID instead of the render target RID
296 	// This is a handy function to expose that.
297 	RID *render_target = (RID *)p_render_target;
298 
299 	RID eye_texture = VSG::storage->render_target_get_texture(*render_target);
300 	uint32_t texid = VS::get_singleton()->texture_get_texid(eye_texture);
301 
302 	return texid;
303 }
304 
godot_arvr_add_controller(char * p_device_name,godot_int p_hand,godot_bool p_tracks_orientation,godot_bool p_tracks_position)305 godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
306 	ARVRServer *arvr_server = ARVRServer::get_singleton();
307 	ERR_FAIL_NULL_V(arvr_server, 0);
308 
309 	InputDefault *input = (InputDefault *)Input::get_singleton();
310 	ERR_FAIL_NULL_V(input, 0);
311 
312 	ARVRPositionalTracker *new_tracker = memnew(ARVRPositionalTracker);
313 	new_tracker->set_name(p_device_name);
314 	new_tracker->set_type(ARVRServer::TRACKER_CONTROLLER);
315 	if (p_hand == 1) {
316 		new_tracker->set_hand(ARVRPositionalTracker::TRACKER_LEFT_HAND);
317 	} else if (p_hand == 2) {
318 		new_tracker->set_hand(ARVRPositionalTracker::TRACKER_RIGHT_HAND);
319 	}
320 
321 	// also register as joystick...
322 	int joyid = input->get_unused_joy_id();
323 	if (joyid != -1) {
324 		new_tracker->set_joy_id(joyid);
325 		input->joy_connection_changed(joyid, true, p_device_name, "");
326 	}
327 
328 	if (p_tracks_orientation) {
329 		Basis orientation;
330 		new_tracker->set_orientation(orientation);
331 	}
332 	if (p_tracks_position) {
333 		Vector3 position;
334 		new_tracker->set_position(position);
335 	}
336 
337 	// add our tracker to our server and remember its pointer
338 	arvr_server->add_tracker(new_tracker);
339 
340 	// note, this ID is only unique within controllers!
341 	return new_tracker->get_tracker_id();
342 }
343 
godot_arvr_remove_controller(godot_int p_controller_id)344 void GDAPI godot_arvr_remove_controller(godot_int p_controller_id) {
345 	ARVRServer *arvr_server = ARVRServer::get_singleton();
346 	ERR_FAIL_NULL(arvr_server);
347 
348 	InputDefault *input = (InputDefault *)Input::get_singleton();
349 	ERR_FAIL_NULL(input);
350 
351 	ARVRPositionalTracker *remove_tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
352 	if (remove_tracker != NULL) {
353 		// unset our joystick if applicable
354 		int joyid = remove_tracker->get_joy_id();
355 		if (joyid != -1) {
356 			input->joy_connection_changed(joyid, false, "", "");
357 			remove_tracker->set_joy_id(-1);
358 		}
359 
360 		// remove our tracker from our server
361 		arvr_server->remove_tracker(remove_tracker);
362 		memdelete(remove_tracker);
363 	}
364 }
365 
godot_arvr_set_controller_transform(godot_int p_controller_id,godot_transform * p_transform,godot_bool p_tracks_orientation,godot_bool p_tracks_position)366 void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
367 	ARVRServer *arvr_server = ARVRServer::get_singleton();
368 	ERR_FAIL_NULL(arvr_server);
369 
370 	ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
371 	if (tracker != NULL) {
372 		Transform *transform = (Transform *)p_transform;
373 		if (p_tracks_orientation) {
374 			tracker->set_orientation(transform->basis);
375 		}
376 		if (p_tracks_position) {
377 			tracker->set_rw_position(transform->origin);
378 		}
379 	}
380 }
381 
godot_arvr_set_controller_button(godot_int p_controller_id,godot_int p_button,godot_bool p_is_pressed)382 void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed) {
383 	ARVRServer *arvr_server = ARVRServer::get_singleton();
384 	ERR_FAIL_NULL(arvr_server);
385 
386 	InputDefault *input = (InputDefault *)Input::get_singleton();
387 	ERR_FAIL_NULL(input);
388 
389 	ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
390 	if (tracker != NULL) {
391 		int joyid = tracker->get_joy_id();
392 		if (joyid != -1) {
393 			input->joy_button(joyid, p_button, p_is_pressed);
394 		}
395 	}
396 }
397 
godot_arvr_set_controller_axis(godot_int p_controller_id,godot_int p_axis,godot_real p_value,godot_bool p_can_be_negative)398 void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative) {
399 	ARVRServer *arvr_server = ARVRServer::get_singleton();
400 	ERR_FAIL_NULL(arvr_server);
401 
402 	InputDefault *input = (InputDefault *)Input::get_singleton();
403 	ERR_FAIL_NULL(input);
404 
405 	ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
406 	if (tracker != NULL) {
407 		int joyid = tracker->get_joy_id();
408 		if (joyid != -1) {
409 			InputDefault::JoyAxis jx;
410 			jx.min = p_can_be_negative ? -1 : 0;
411 			jx.value = p_value;
412 			input->joy_axis(joyid, p_axis, jx);
413 		}
414 	}
415 }
416 
godot_arvr_get_controller_rumble(godot_int p_controller_id)417 godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id) {
418 	ARVRServer *arvr_server = ARVRServer::get_singleton();
419 	ERR_FAIL_NULL_V(arvr_server, 0.0);
420 
421 	ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
422 	if (tracker != NULL) {
423 		return tracker->get_rumble();
424 	}
425 
426 	return 0.0;
427 }
428 }
429