Преглед на файлове

Merge pull request #10062 from BastiaanOlij/arvr_add_anchor

Added ARVRAnchor support and a few small enhancements
Rémi Verschelde преди 8 години
родител
ревизия
c51354f504
променени са 5 файла, в които са добавени 184 реда и са изтрити 8 реда
  1. 113 0
      scene/3d/arvr_nodes.cpp
  2. 34 3
      scene/3d/arvr_nodes.h
  3. 1 0
      scene/register_scene_types.cpp
  4. 31 2
      servers/arvr/arvr_positional_tracker.cpp
  5. 5 3
      servers/arvr/arvr_positional_tracker.h

+ 113 - 0
scene/3d/arvr_nodes.cpp

@@ -98,6 +98,7 @@ void ARVRController::_notification(int p_what) {
 				is_active = false;
 				button_states = 0;
 			} else {
+				is_active = true;
 				set_transform(tracker->get_transform(true));
 
 				int joy_id = tracker->get_joy_id();
@@ -231,6 +232,118 @@ ARVRController::~ARVRController(){
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
+void ARVRAnchor::_notification(int p_what) {
+	switch (p_what) {
+		case NOTIFICATION_ENTER_TREE: {
+			set_process_internal(true);
+		}; break;
+		case NOTIFICATION_EXIT_TREE: {
+			set_process_internal(false);
+		}; break;
+		case NOTIFICATION_INTERNAL_PROCESS: {
+			// get our ARVRServer
+			ARVRServer *arvr_server = ARVRServer::get_singleton();
+			ERR_FAIL_NULL(arvr_server);
+
+			// find the tracker for our anchor
+			ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_ANCHOR, anchor_id);
+			if (tracker == NULL) {
+				// this anchor is currently not available
+				is_active = false;
+			} else {
+				is_active = true;
+				Transform transform;
+
+				// we'll need our world_scale
+				real_t world_scale = arvr_server->get_world_scale();
+
+				// get our info from our tracker
+				transform.basis = tracker->get_orientation();
+				transform.origin = tracker->get_position(); // <-- already adjusted to world scale
+
+				// our basis is scaled to the size of the plane the anchor is tracking
+				// extract the size from our basis and reset the scale
+				size = transform.basis.get_scale() * world_scale;
+				transform.basis.set_scale(Vector3(1.0, 1.0, 1.0));
+
+				// apply our reference frame and set our transform
+				set_transform(arvr_server->get_reference_frame() * transform);
+			};
+		}; break;
+		default:
+			break;
+	};
+};
+
+void ARVRAnchor::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_anchor_id", "anchor_id"), &ARVRAnchor::set_anchor_id);
+	ClassDB::bind_method(D_METHOD("get_anchor_id"), &ARVRAnchor::get_anchor_id);
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id"), "set_anchor_id", "get_anchor_id");
+	ClassDB::bind_method(D_METHOD("get_anchor_name"), &ARVRAnchor::get_anchor_name);
+
+	ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRAnchor::get_is_active);
+	ClassDB::bind_method(D_METHOD("get_size"), &ARVRAnchor::get_size);
+};
+
+void ARVRAnchor::set_anchor_id(int p_anchor_id) {
+	// we don't check any bounds here, this anchor may not yet be active and just be a place holder until it is.
+	anchor_id = p_anchor_id;
+};
+
+int ARVRAnchor::get_anchor_id(void) const {
+	return anchor_id;
+};
+
+Vector3 ARVRAnchor::get_size() const {
+	return size;
+};
+
+String ARVRAnchor::get_anchor_name(void) const {
+	// get our ARVRServer
+	ARVRServer *arvr_server = ARVRServer::get_singleton();
+	ERR_FAIL_NULL_V(arvr_server, String());
+
+	ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_ANCHOR, anchor_id);
+	if (tracker == NULL) {
+		return String("Not connected");
+	};
+
+	return tracker->get_name();
+};
+
+bool ARVRAnchor::get_is_active() const {
+	return is_active;
+};
+
+String ARVRAnchor::get_configuration_warning() const {
+	if (!is_visible() || !is_inside_tree())
+		return String();
+
+	// must be child node of ARVROrigin!
+	ARVROrigin *origin = get_parent()->cast_to<ARVROrigin>();
+	if (origin == NULL) {
+		return TTR("ARVRAnchor must have an ARVROrigin node as its parent");
+	};
+
+	if (anchor_id == 0) {
+		return TTR("The anchor id must not be 0 or this anchor will not be bound to an actual anchor");
+	};
+
+	return String();
+};
+
+ARVRAnchor::ARVRAnchor() {
+	anchor_id = 0;
+	is_active = true;
+};
+
+ARVRAnchor::~ARVRAnchor(){
+	// nothing to do here yet for now..
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
 String ARVROrigin::get_configuration_warning() const {
 	if (!is_visible() || !is_inside_tree())
 		return String();

+ 34 - 3
scene/3d/arvr_nodes.h

@@ -39,7 +39,7 @@
 **/
 
 /*
-  ARVRCamera is a subclass of camera which will register itself with its parent ARVROrigin and as a result is automatically positioned
+	ARVRCamera is a subclass of camera which will register itself with its parent ARVROrigin and as a result is automatically positioned
 */
 class ARVRCamera : public Camera {
 
@@ -56,9 +56,9 @@ public:
 };
 
 /*
-  ARVRController is a helper node that automatically updates it's position based on tracker data.
+	ARVRController is a helper node that automatically updates it's position based on tracker data.
 
-  It must be a child node of our ARVROrigin node
+	It must be a child node of our ARVROrigin node
 */
 
 class ARVRController : public Spatial {
@@ -91,6 +91,37 @@ public:
 	~ARVRController();
 };
 
+/*
+	ARVRAnchor is a helper node that automatically updates it's position based on anchor data, it represents a real world location.
+	It must be a child node of our ARVROrigin node
+*/
+
+class ARVRAnchor : public Spatial {
+	GDCLASS(ARVRAnchor, Spatial);
+
+private:
+	int anchor_id;
+	bool is_active;
+	Vector3 size;
+
+protected:
+	void _notification(int p_what);
+	static void _bind_methods();
+
+public:
+	void set_anchor_id(int p_anchor_id);
+	int get_anchor_id(void) const;
+	String get_anchor_name(void) const;
+
+	bool get_is_active() const;
+	Vector3 get_size() const;
+
+	String get_configuration_warning() const;
+
+	ARVRAnchor();
+	~ARVRAnchor();
+};
+
 /*
 	ARVROrigin is special spatial node that acts as our origin point mapping our real world center of our tracking volume into our virtual world.
 

+ 1 - 0
scene/register_scene_types.cpp

@@ -409,6 +409,7 @@ void register_scene_types() {
 	ClassDB::register_class<Listener>();
 	ClassDB::register_class<ARVRCamera>();
 	ClassDB::register_class<ARVRController>();
+	ClassDB::register_class<ARVRAnchor>();
 	ClassDB::register_class<ARVROrigin>();
 	ClassDB::register_class<InterpolatedCamera>();
 	ClassDB::register_class<MeshInstance>();

+ 31 - 2
servers/arvr/arvr_positional_tracker.cpp

@@ -40,6 +40,13 @@ void ARVRPositionalTracker::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_tracks_position"), &ARVRPositionalTracker::get_tracks_position);
 	ClassDB::bind_method(D_METHOD("get_position"), &ARVRPositionalTracker::get_position);
 	ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &ARVRPositionalTracker::get_transform);
+
+	// these functions we don't want to expose to normal users but do need to be callable from GDNative
+	ClassDB::bind_method(D_METHOD("_set_type", "type"), &ARVRPositionalTracker::set_type);
+	ClassDB::bind_method(D_METHOD("_set_name", "name"), &ARVRPositionalTracker::set_name);
+	ClassDB::bind_method(D_METHOD("_set_joy_id", "joy_id"), &ARVRPositionalTracker::set_joy_id);
+	ClassDB::bind_method(D_METHOD("_set_orientation", "orientation"), &ARVRPositionalTracker::set_orientation);
+	ClassDB::bind_method(D_METHOD("_set_rw_position", "rw_position"), &ARVRPositionalTracker::set_rw_position);
 };
 
 void ARVRPositionalTracker::set_type(ARVRServer::TrackerType p_type) {
@@ -102,14 +109,36 @@ bool ARVRPositionalTracker::get_tracks_position() const {
 void ARVRPositionalTracker::set_position(const Vector3 &p_position) {
 	_THREAD_SAFE_METHOD_
 
+	ARVRServer *arvr_server = ARVRServer::get_singleton();
+	ERR_FAIL_NULL(arvr_server);
+	real_t world_scale = arvr_server->get_world_scale();
+	ERR_FAIL_COND(world_scale == 0);
+
 	tracks_position = true; // obviously we have this
-	position = p_position;
+	rw_position = p_position / world_scale;
 };
 
 Vector3 ARVRPositionalTracker::get_position() const {
 	_THREAD_SAFE_METHOD_
 
-	return position;
+	ARVRServer *arvr_server = ARVRServer::get_singleton();
+	ERR_FAIL_NULL_V(arvr_server, rw_position);
+	real_t world_scale = arvr_server->get_world_scale();
+
+	return rw_position * world_scale;
+};
+
+void ARVRPositionalTracker::set_rw_position(const Vector3 &p_rw_position) {
+	_THREAD_SAFE_METHOD_
+
+	tracks_position = true; // obviously we have this
+	rw_position = p_rw_position;
+};
+
+Vector3 ARVRPositionalTracker::get_rw_position() const {
+	_THREAD_SAFE_METHOD_
+
+	return rw_position;
 };
 
 Transform ARVRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const {

+ 5 - 3
servers/arvr/arvr_positional_tracker.h

@@ -56,7 +56,7 @@ private:
 	bool tracks_orientation; // do we track orientation?
 	Basis orientation; // our orientation
 	bool tracks_position; // do we track position?
-	Vector3 position; // our position
+	Vector3 rw_position; // our position "in the real world, so without world_scale applied"
 
 protected:
 	static void _bind_methods();
@@ -73,8 +73,10 @@ public:
 	void set_orientation(const Basis &p_orientation);
 	Basis get_orientation() const;
 	bool get_tracks_position() const;
-	void set_position(const Vector3 &p_position);
-	Vector3 get_position() const;
+	void set_position(const Vector3 &p_position); // set position with world_scale applied
+	Vector3 get_position() const; // get position with world_scale applied
+	void set_rw_position(const Vector3 &p_rw_position);
+	Vector3 get_rw_position() const;
 
 	Transform get_transform(bool p_adjust_by_reference_frame) const;