float * psmove_fusion_get_modelview_matrix(PSMoveFusion *fusion, PSMove *move) { psmove_return_val_if_fail(fusion != NULL, NULL); psmove_return_val_if_fail(move != NULL, NULL); float q0, q1, q2, q3; psmove_get_orientation(move, &q0, &q1, &q2, &q3); if (psmove_tracker_get_mirror(fusion->tracker)) { /* Need to invert these two axes if mirroring is enabled */ q3 *= -1.; q2 *= -1.; } glm::quat quaternion(q3, q2, q1, q0); float x, y, z; psmove_fusion_get_position(fusion, move, &x, &y, &z); fusion->modelview = glm::translate(glm::mat4(), glm::vec3(x, y, z)) * glm::mat4_cast(quaternion); return glm::value_ptr(fusion->modelview); }
uint32 FPSMoveWorker::Run() { if (!psmove_init(PSMOVE_CURRENT_VERSION)) { UE_LOG(LogPSMove, Error, TEXT("PS Move API init failed (wrong version?)")); return -1; } // I want the psmoves and psmove_tracker to be local variables in the thread. // Initialize an empty array of psmove controllers PSMove* psmoves[FPSMoveWorker::k_max_controllers]; memset(psmoves, 0, sizeof(psmoves)); // Initialize and configure the psmove_tracker PSMoveTracker *psmove_tracker = psmove_tracker_new(); // Unfortunately the API does not have a way to change the resolution and framerate. PSMoveFusion *psmove_fusion = psmove_fusion_new(psmove_tracker, 1., 1000.); int tracker_width = 640; int tracker_height = 480; if (psmove_tracker) { UE_LOG(LogPSMove, Log, TEXT("PSMove tracker initialized.")); //Set exposure. TODO: Expose this to component. psmove_tracker_set_exposure(psmove_tracker, Exposure_LOW); //Exposure_LOW, Exposure_MEDIUM, Exposure_HIGH psmove_tracker_set_smoothing(psmove_tracker, 0, 1); psmove_tracker_set_mirror(psmove_tracker, PSMove_True); psmove_tracker_get_size(psmove_tracker, &tracker_width, &tracker_height); UE_LOG(LogPSMove, Log, TEXT("Camera Dimensions: %d x %d"), tracker_width, tracker_height); } else { UE_LOG(LogPSMove, Log, TEXT("PSMove tracker failed to initialize.")); } //Initial wait before starting. FPlatformProcess::Sleep(0.03); float xcm, ycm, zcm, oriw, orix, oriy, oriz; while (StopTaskCounter.GetValue() == 0) { // Get positional data from tracker if (psmove_tracker) { // Setup or tear down controller connections based on the number of active controllers UpdateControllerConnections(psmove_tracker, psmoves); // Renew the image on camera if (PSMoveCount > 0) { psmove_tracker_update_image(psmove_tracker); // Sometimes libusb crashes here. psmove_tracker_update_cbb(psmove_tracker, NULL); // Passing null (instead of m_moves[i]) updates all controllers. } } else { FPlatformProcess::Sleep(0.001); } for (int i = 0; i < PSMoveCount; i++) { FPSMoveRawControllerData_TLS &localControllerData = WorkerControllerDataArray[i]; //-------------- // Read the published data from the component //-------------- localControllerData.WorkerRead(); // Get positional data from tracker if (psmove_tracker) { localControllerData.IsTracked = psmove_tracker_get_status(psmove_tracker, psmoves[i]) == Tracker_TRACKING; psmove_fusion_get_transformed_location(psmove_fusion, psmoves[i], &xcm, &ycm, &zcm); if (localControllerData.IsTracked && xcm && ycm && zcm && !isnan(xcm) && !isnan(ycm) && !isnan(zcm) && xcm == xcm && ycm == ycm && zcm == zcm) { localControllerData.PosX = xcm; localControllerData.PosY = ycm; localControllerData.PosZ = zcm; } else { localControllerData.IsTracked = false; } //UE_LOG(LogPSMove, Log, TEXT("X: %f, Y: %f, Z: %f"), xcm, ycm, zcm); if (localControllerData.ResetPoseRequest && localControllerData.IsTracked) { psmove_tracker_reset_location(psmove_tracker, psmoves[i]); } // If we are to change the tracked colour. if (localControllerData.UpdateLedRequest) { // Stop tracking the controller with the existing color psmove_tracker_disable(psmove_tracker, psmoves[i]); localControllerData.IsTracked = false; localControllerData.IsCalibrated = false; psmove_tracker_set_dimming(psmove_tracker, 0.0); // Set dimming to 0 to trigger blinking calibration. psmove_set_leds(psmoves[i], 0, 0, 0); // Turn off the LED to make sure it isn't trackable until new colour set. psmove_update_leds(psmoves[i]); FColor newFColor = localControllerData.LedColourRequest.Quantize(); if (psmove_tracker_enable_with_color(psmove_tracker, psmoves[i], newFColor.R, newFColor.G, newFColor.B) == Tracker_CALIBRATED) { this->WorkerControllerDataArray[i].IsCalibrated = true; } else { UE_LOG(LogPSMove, Error, TEXT("Failed to change tracking color for PSMove controller %d"), i); } localControllerData.LedColourWasUpdated = true; } else { localControllerData.LedColourWasUpdated = false; } } else { FPlatformProcess::Sleep(0.001); } // Do bluetooth IO: Orientation, Buttons, Rumble //TODO: Is it necessary to keep polling until no frames are left? while (psmove_poll(psmoves[i]) > 0) { // Update the controller status (via bluetooth) psmove_poll(psmoves[i]); // Get the controller orientation (uses IMU). psmove_get_orientation(psmoves[i], &oriw, &orix, &oriy, &oriz); localControllerData.OriW = oriw; localControllerData.OriX = orix; localControllerData.OriY = oriy; localControllerData.OriZ = oriz; //UE_LOG(LogPSMove, Log, TEXT("Ori w,x,y,z: %f, %f, %f, %f"), oriw, orix, oriy, oriz); // Get the controller button state localControllerData.Buttons = psmove_get_buttons(psmoves[i]); // Bitwise; tells if each button is down. psmove_get_button_events(psmoves[i], &localControllerData.Pressed, &localControllerData.Released); // i.e., state change // Get the controller trigger value (uint8; 0-255) localControllerData.TriggerValue = psmove_get_trigger(psmoves[i]); // Set the controller rumble (uint8; 0-255) psmove_set_rumble(psmoves[i], localControllerData.RumbleRequest); } if (localControllerData.ResetPoseRequest) { psmove_reset_orientation(psmoves[i]); //TODO: reset yaw only localControllerData.PoseWasReset = true; } else { localControllerData.PoseWasReset = false; } //-------------- // Publish the updated worker data to the component //-------------- localControllerData.WorkerPost(); } //Sleeping the thread seems to crash libusb. //FPlatformProcess::Sleep(0.005); } // Delete the controllers for (int i = 0; i<PSMoveCount; i++) { psmove_disconnect(psmoves[i]); } // Delete the fusion if (psmove_fusion) { psmove_fusion_free(psmove_fusion); } // Delete the tracker if (psmove_tracker) { psmove_tracker_free(psmove_tracker); } psmove_shutdown(); return 0; }