Torque3D/Engine/source/platform/input/openVR/openVRTrackedObject.cpp

982 lines
28 KiB
C++
Raw Normal View History

#include "platform/platform.h"
#include "platform/input/openVR/openVRTrackedObject.h"
#include "platform/input/openVR/openVRProvider.h"
#include "math/mathIO.h"
#include "scene/sceneRenderState.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "core/resourceManager.h"
#include "materials/materialManager.h"
#include "materials/baseMatInstance.h"
#include "renderInstance/renderPassManager.h"
#include "lighting/lightQuery.h"
#include "console/engineAPI.h"
#include "gfx/gfxTextureManager.h"
#include "gfx/sim/debugDraw.h"
#include "gfx/gfxTransformSaver.h"
#include "environment/skyBox.h"
#include "collision/boxConvex.h"
#include "collision/concretePolyList.h"
#include "T3D/physics/physicsPlugin.h"
#include "T3D/physics/physicsCollision.h"
#include "T3D/physics/physicsBody.h"
#ifdef TORQUE_EXTENDED_MOVE
#include "T3D/gameBase/extended/extendedMove.h"
#endif
bool OpenVRTrackedObject::smDebugControllerMovePosition = true;
bool OpenVRTrackedObject::smDebugControllerPosition = false;
static const U32 sCollisionMoveMask = (PlayerObjectType |
2016-07-12 22:30:11 +00:00
StaticShapeObjectType | VehicleObjectType);
U32 OpenVRTrackedObject::sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
U32 OpenVRTrackedObject::sClientCollisionMask = sCollisionMoveMask;
//-----------------------------------------------------------------------------
IMPLEMENT_CO_DATABLOCK_V1(OpenVRTrackedObjectData);
OpenVRTrackedObjectData::OpenVRTrackedObjectData() :
mShapeFile(NULL)
{
2016-07-12 22:30:11 +00:00
mCollisionBoxMin = Point3F(-0.02, -0.20, -0.02);
mCollisionBoxMax = Point3F(0.02, 0.05, 0.02);
}
OpenVRTrackedObjectData::~OpenVRTrackedObjectData()
{
}
bool OpenVRTrackedObjectData::onAdd()
{
2016-07-12 22:30:11 +00:00
if (Parent::onAdd())
{
return true;
}
2016-07-12 22:30:11 +00:00
return false;
}
bool OpenVRTrackedObjectData::preload(bool server, String &errorStr)
{
2016-07-12 22:30:11 +00:00
if (!Parent::preload(server, errorStr))
return false;
2016-07-12 22:30:11 +00:00
bool error = false;
if (!server)
{
mShape = mShapeFile ? ResourceManager::get().load(mShapeFile) : NULL;
}
}
void OpenVRTrackedObjectData::initPersistFields()
{
2016-07-12 22:30:11 +00:00
addGroup("Render Components");
addField("shape", TypeShapeFilename, Offset(mShapeFile, OpenVRTrackedObjectData), "Shape file to use for controller model.");
addField("collisionMin", TypePoint3F, Offset(mCollisionBoxMin, OpenVRTrackedObjectData), "Box min");
addField("collisionMax", TypePoint3F, Offset(mCollisionBoxMax, OpenVRTrackedObjectData), "Box min");
endGroup("Render Components");
2016-07-12 22:30:11 +00:00
Parent::initPersistFields();
}
void OpenVRTrackedObjectData::packData(BitStream* stream)
{
2016-07-12 22:30:11 +00:00
Parent::packData(stream);
2016-07-12 22:30:11 +00:00
stream->writeString(mShapeFile);
}
void OpenVRTrackedObjectData::unpackData(BitStream* stream)
{
2016-07-12 22:30:11 +00:00
Parent::unpackData(stream);
2016-07-12 22:30:11 +00:00
mShapeFile = stream->readSTString();
}
//-----------------------------------------------------------------------------
IMPLEMENT_CO_NETOBJECT_V1(OpenVRTrackedObject);
ConsoleDocClass(OpenVRTrackedObject,
2016-07-12 22:30:11 +00:00
"@brief Renders and handles interactions OpenVR controllers and tracked objects.\n\n"
"This class implements basic rendering and interactions with OpenVR controllers.\n\n"
"The object should be controlled by a player object. Controllers will be rendered at\n"
"the correct position regardless of the current transform of the object.\n"
"@ingroup OpenVR\n");
//-----------------------------------------------------------------------------
// Object setup and teardown
//-----------------------------------------------------------------------------
OpenVRTrackedObject::OpenVRTrackedObject() :
mDataBlock(NULL),
mShapeInstance(NULL),
mBasicModel(NULL),
mDeviceIndex(-1),
mMappedMoveIndex(-1),
mIgnoreParentRotation(true),
mConvexList(new Convex()),
mPhysicsRep(NULL)
{
2016-07-12 22:30:11 +00:00
// Flag this object so that it will always
// be sent across the network to clients
mNetFlags.set(Ghostable | ScopeAlways);
2016-07-12 22:30:11 +00:00
// Set it as a "static" object that casts shadows
mTypeMask |= StaticObjectType | StaticShapeObjectType;
2016-07-12 22:30:11 +00:00
mPose.connected = false;
}
OpenVRTrackedObject::~OpenVRTrackedObject()
{
2016-07-12 22:30:11 +00:00
clearRenderData();
delete mConvexList;
}
void OpenVRTrackedObject::updateRenderData()
{
2016-07-12 22:30:11 +00:00
clearRenderData();
2016-07-12 22:30:11 +00:00
if (!mDataBlock)
return;
2016-07-12 22:30:11 +00:00
// Are we using a model?
if (mDataBlock->mShape)
{
if (mShapeInstance && mShapeInstance->getShape() != mDataBlock->mShape)
{
delete mShapeInstance;
mShapeInstance = NULL;
}
2016-07-12 22:30:11 +00:00
if (!mShapeInstance)
{
mShapeInstance = new TSShapeInstance(mDataBlock->mShape, isClientObject());
}
}
else
{
setupRenderDataFromModel(isClientObject());
}
}
void OpenVRTrackedObject::setupRenderDataFromModel(bool loadComponentModels)
{
2016-07-12 22:30:11 +00:00
clearRenderData();
if (!OPENVR || !OPENVR->isEnabled())
return;
vr::IVRRenderModels *models = OPENVR->getRenderModels();
if (!models)
return;
if (!mShapeInstance && mModelName && mModelName[0] != '\0')
{
bool failed = false;
S32 idx = OPENVR->preloadRenderModel(mModelName);
while (!OPENVR->getRenderModel(idx, &mBasicModel, failed))
{
if (failed)
break;
}
}
if (loadComponentModels)
{
mRenderComponents.setSize(models->GetComponentCount(mModelName));
for (U32 i = 0, sz = mRenderComponents.size(); i < sz; i++)
{
RenderModelSlot &slot = mRenderComponents[i];
char buffer[1024];
slot.mappedNodeIdx = -1;
slot.componentName = NULL;
slot.nativeModel = NULL;
U32 result = models->GetComponentName(mModelName, i, buffer, sizeof(buffer));
if (result == 0)
continue;
#ifdef DEBUG_CONTROLLER_MODELS
2016-07-12 22:30:11 +00:00
Con::printf("Controller[%s] component %i NAME == %s", mModelName, i, buffer);
#endif
2016-07-12 22:30:11 +00:00
slot.componentName = StringTable->insert(buffer, true);
2016-07-12 22:30:11 +00:00
result = models->GetComponentRenderModelName(mModelName, slot.componentName, buffer, sizeof(buffer));
if (result == 0)
{
#ifdef DEBUG_CONTROLLER_MODELS
2016-07-12 22:30:11 +00:00
Con::printf("Controller[%s] component %i NO MODEL", mModelName, i);
#endif
2016-07-12 22:30:11 +00:00
continue;
}
#ifdef DEBUG_CONTROLLER_MODELS
2016-07-12 22:30:11 +00:00
Con::printf("Controller[%s] component %i == %s", mModelName, i, slot.componentName);
#endif
2016-07-12 22:30:11 +00:00
bool failed = false;
S32 idx = OPENVR->preloadRenderModel(StringTable->insert(buffer, true));
while (!OPENVR->getRenderModel(idx, &slot.nativeModel, failed))
{
if (failed)
break;
}
}
}
}
void OpenVRTrackedObject::clearRenderData()
{
2016-07-12 22:30:11 +00:00
mBasicModel = NULL;
mRenderComponents.clear();
}
//-----------------------------------------------------------------------------
// Object Editing
//-----------------------------------------------------------------------------
void OpenVRTrackedObject::initPersistFields()
{
2016-07-12 22:30:11 +00:00
// SceneObject already handles exposing the transform
Parent::initPersistFields();
2016-07-12 22:30:11 +00:00
addField("deviceIndex", TypeS32, Offset(mDeviceIndex, OpenVRTrackedObject), "Index of device to track");
addField("mappedMoveIndex", TypeS32, Offset(mMappedMoveIndex, OpenVRTrackedObject), "Index of movemanager state to track"); addField("deviceIndex", TypeS32, Offset(mDeviceIndex, OpenVRTrackedObject), "Index of device to track");
addField("ignoreParentRotation", TypeBool, Offset(mIgnoreParentRotation, OpenVRTrackedObject), "Index of movemanager state to track"); addField("deviceIndex", TypeS32, Offset(mDeviceIndex, OpenVRTrackedObject), "Index of device to track");
2016-07-12 22:30:11 +00:00
static bool conInit = false;
if (!conInit)
{
Con::addVariable("$OpenVRTrackedObject::debugControllerPosition", TypeBool, &smDebugControllerPosition);
Con::addVariable("$OpenVRTrackedObject::debugControllerMovePosition", TypeBool, &smDebugControllerMovePosition);
conInit = true;
}
}
void OpenVRTrackedObject::inspectPostApply()
{
2016-07-12 22:30:11 +00:00
Parent::inspectPostApply();
2016-07-12 22:30:11 +00:00
// Flag the network mask to send the updates
// to the client object
setMaskBits(UpdateMask);
}
bool OpenVRTrackedObject::onAdd()
{
2016-07-12 22:30:11 +00:00
if (!Parent::onAdd())
return false;
2016-07-12 22:30:11 +00:00
// Set up a 1x1x1 bounding box
mObjBox.set(Point3F(-0.5f, -0.5f, -0.5f),
Point3F(0.5f, 0.5f, 0.5f));
2016-07-12 22:30:11 +00:00
resetWorldBox();
2016-07-12 22:30:11 +00:00
// Add this object to the scene
addToScene();
2016-07-12 22:30:11 +00:00
if (mDataBlock)
{
mObjBox.minExtents = mDataBlock->mCollisionBoxMin;
mObjBox.maxExtents = mDataBlock->mCollisionBoxMax;
resetWorldBox();
}
else
{
setGlobalBounds();
}
2016-07-12 22:30:11 +00:00
return true;
}
void OpenVRTrackedObject::onRemove()
{
2016-07-12 22:30:11 +00:00
// Remove this object from the scene
removeFromScene();
2016-07-12 22:30:11 +00:00
clearRenderData();
2016-07-12 22:30:11 +00:00
SAFE_DELETE(mPhysicsRep);
2016-07-12 22:30:11 +00:00
Parent::onRemove();
}
void OpenVRTrackedObject::_updatePhysics()
{
2016-07-12 22:30:11 +00:00
SAFE_DELETE(mPhysicsRep);
2016-07-12 22:30:11 +00:00
if (!PHYSICSMGR)
return;
2016-07-12 22:30:11 +00:00
PhysicsCollision *colShape = NULL;
MatrixF offset(true);
colShape = PHYSICSMGR->createCollision();
colShape->addBox(getObjBox().getExtents() * 0.5f * mObjScale, offset);
2016-07-12 22:30:11 +00:00
if (colShape)
{
PhysicsWorld *world = PHYSICSMGR->getWorld(isServerObject() ? "server" : "client");
mPhysicsRep = PHYSICSMGR->createBody();
mPhysicsRep->init(colShape, 0, PhysicsBody::BF_TRIGGER | PhysicsBody::BF_KINEMATIC, this, world);
mPhysicsRep->setTransform(getTransform());
}
}
bool OpenVRTrackedObject::onNewDataBlock(GameBaseData *dptr, bool reload)
{
2016-07-12 22:30:11 +00:00
mDataBlock = dynamic_cast<OpenVRTrackedObjectData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
return false;
2016-07-12 22:30:11 +00:00
// Setup the models
clearRenderData();
2016-07-12 22:30:11 +00:00
mObjBox.minExtents = mDataBlock->mCollisionBoxMin;
mObjBox.maxExtents = mDataBlock->mCollisionBoxMax;
2016-07-12 22:30:11 +00:00
mGlobalBounds = false;
2016-07-12 22:30:11 +00:00
resetWorldBox();
2016-07-12 22:30:11 +00:00
_updatePhysics();
2016-07-12 22:30:11 +00:00
scriptOnNewDataBlock();
2016-07-12 22:30:11 +00:00
return true;
}
void OpenVRTrackedObject::setInteractObject(SceneObject* object, bool holding)
{
2016-07-12 22:30:11 +00:00
mInteractObject = object;
mHoldInteractedObject = holding;
}
void OpenVRTrackedObject::setTransform(const MatrixF & mat)
{
2016-07-12 22:30:11 +00:00
// Let SceneObject handle all of the matrix manipulation
Parent::setTransform(mat);
2016-07-12 22:30:11 +00:00
// Dirty our network mask so that the new transform gets
// transmitted to the client object
setMaskBits(UpdateMask);
}
void OpenVRTrackedObject::setModelName(String &modelName)
{
2016-07-12 22:30:11 +00:00
if (!isServerObject())
return;
2016-07-12 22:30:11 +00:00
mModelName = StringTable->insert(modelName.c_str(), true);
setMaskBits(UpdateMask);
}
U32 OpenVRTrackedObject::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
{
2016-07-12 22:30:11 +00:00
// Allow the Parent to get a crack at writing its info
U32 retMask = Parent::packUpdate(conn, mask, stream);
2016-07-12 22:30:11 +00:00
// Write our transform information
if (stream->writeFlag(mask & UpdateMask))
{
mathWrite(*stream, getTransform());
mathWrite(*stream, getScale());
2016-07-12 22:30:11 +00:00
stream->write((S16)mDeviceIndex);
stream->write((S16)mMappedMoveIndex);
stream->writeString(mModelName);
}
2016-07-12 22:30:11 +00:00
return retMask;
}
void OpenVRTrackedObject::unpackUpdate(NetConnection *conn, BitStream *stream)
{
2016-07-12 22:30:11 +00:00
// Let the Parent read any info it sent
Parent::unpackUpdate(conn, stream);
2016-07-12 22:30:11 +00:00
if (stream->readFlag()) // UpdateMask
{
mathRead(*stream, &mObjToWorld);
mathRead(*stream, &mObjScale);
2016-07-12 22:30:11 +00:00
setTransform(mObjToWorld);
S16 readDeviceIndex;
S16 readMoveIndex;
stream->read(&readDeviceIndex);
stream->read(&readMoveIndex);
2016-07-12 22:30:11 +00:00
mDeviceIndex = readDeviceIndex;
mMappedMoveIndex = readMoveIndex;
mModelName = stream->readSTString();
2016-07-12 22:30:11 +00:00
updateRenderData();
}
}
void OpenVRTrackedObject::writePacketData(GameConnection *conn, BitStream *stream)
{
2016-07-12 22:30:11 +00:00
Parent::writePacketData(conn, stream);
}
void OpenVRTrackedObject::readPacketData(GameConnection *conn, BitStream *stream)
{
2016-07-12 22:30:11 +00:00
Parent::readPacketData(conn, stream);
}
MatrixF OpenVRTrackedObject::getTrackedTransform()
{
2016-07-12 22:30:11 +00:00
IDevicePose pose = OPENVR->getTrackedDevicePose(mDeviceIndex);
MatrixF trackedMat(1);
2016-07-12 22:30:11 +00:00
pose.orientation.setMatrix(&trackedMat);
trackedMat.setPosition(pose.position);
2016-07-12 22:30:11 +00:00
return trackedMat;
}
MatrixF OpenVRTrackedObject::getLastTrackedTransform()
{
2016-07-12 22:30:11 +00:00
MatrixF trackedMat(1);
2016-07-12 22:30:11 +00:00
mPose.orientation.setMatrix(&trackedMat);
trackedMat.setPosition(mPose.position);
2016-07-12 22:30:11 +00:00
return trackedMat;
}
MatrixF OpenVRTrackedObject::getBaseTrackingTransform()
{
2016-07-12 22:30:11 +00:00
if (isMounted())
{
MatrixF mat;
2016-07-12 22:30:11 +00:00
mMount.object->getMountTransform(mMount.node, mMount.xfm, &mat);
if (mIgnoreParentRotation)
{
Point3F pos = mat.getPosition();
mat = MatrixF(1);
mat.setPosition(pos);
}
//mat.inverse();
return mat;
}
2016-07-12 22:30:11 +00:00
return MatrixF(1);
}
void OpenVRTrackedObject::prepRenderImage(SceneRenderState *state)
{
2016-07-12 22:30:11 +00:00
RenderPassManager *renderPass = state->getRenderPass();
// debug rendering for now
if (mDeviceIndex < 0)
return;
// Current pose
IDevicePose pose = OPENVR->getTrackedDevicePose(mDeviceIndex);
IDevicePose hmdPose = OPENVR->getTrackedDevicePose(0);
if (!pose.connected && !mPose.connected)
return;
MatrixF offsetMat = getBaseTrackingTransform();
//offsetMat.inverse();
Point3F pos = offsetMat.getPosition();
//Con::printf("Base offs == %f,%f,%f", pos.x, pos.y, pos.z);
const F32 CONTROLLER_SCALE = 0.1;
if (smDebugControllerPosition)
{
ColorI drawColor = ColorI::GREEN;
if (!pose.valid)
{
drawColor = ColorI::RED;
}
// Draw Camera
/*
DisplayPose cameraPose;
OPENVR->getFrameEyePose(&cameraPose, -1);
Point3F cameraCenter(0);
MatrixF cameraMat(1);
cameraPose.orientation.setMatrix(&cameraMat);
cameraMat.setPosition(cameraPose.position);
cameraMat.mulP(cameraCenter);
//DebugDrawer::get()->drawBox(cameraCenter - Point3F(0.1), cameraCenter + Point3F(0.1), ColorI::GREEN);
DebugDrawer::get()->drawTransformedBoxOutline(Point3F(-0.5, -0.1, -0.5), Point3F(0.5, 0.1, 0.5), ColorI::WHITE, cameraMat); // general box
*/
// Draw Tracked HMD Pos
Point3F hmdCenter(0, 0, 0);
MatrixF hmdMat(1);
hmdPose.orientation.setMatrix(&hmdMat);
hmdMat.setPosition(hmdPose.position);
hmdMat.inverse(); // -> world mat (as opposed to world -> tracked pos)
hmdMat = offsetMat * hmdMat;
hmdMat.mulP(hmdCenter);
DebugDrawer::get()->drawBox(hmdCenter - Point3F(0.1), hmdCenter + Point3F(0.1), ColorI::RED);
DebugDrawer::get()->drawTransformedBoxOutline(Point3F(-0.5, -0.1, -0.5), Point3F(0.5, 0.1, 0.5), ColorI::GREEN, hmdMat); // general box
// Draw Controller
MatrixF mat(1);
pose.orientation.setMatrix(&mat);
mat.setPosition(pose.position);
mat.inverse(); // same as HMD
mat = offsetMat * mat;
Point3F middleStart(0, -1 * CONTROLLER_SCALE, 0);
Point3F middleEnd(0, 1 * CONTROLLER_SCALE, 0);
Point3F middle(0, 0, 0);
Point3F center(0, 0, 0);
mat.mulP(center);
//DebugDrawer::get()->drawBox(center - Point3F(0.1), center + Point3F(0.1), ColorI::BLUE);
mat.mulP(middleStart);
mat.mulP(middle);
mat.mulP(middleEnd);
char buffer[256];
dSprintf(buffer, 256, "%f %f %f", center.x, center.y, center.z);
DebugDrawer::get()->drawText(middle, buffer);
DebugDrawer::get()->drawLine(middleStart, middle, ColorI(0, 255, 0)); // axis back
DebugDrawer::get()->drawLine(middleEnd, middle, ColorI(255, 0, 0)); // axis forward
DebugDrawer::get()->drawTransformedBoxOutline(Point3F(-0.5, -1, -0.5) * CONTROLLER_SCALE, Point3F(0.5, 1, 0.5) * CONTROLLER_SCALE, drawColor, mat); // general box
DebugDrawer::get()->drawBoxOutline(Point3F(-1), Point3F(1), ColorI::WHITE);
}
if (isClientObject() && smDebugControllerMovePosition)
{
MatrixF transform = getRenderTransform();
transform.scale(mObjScale);
DebugDrawer::get()->drawTransformedBoxOutline(mObjBox.minExtents, mObjBox.maxExtents, ColorI::RED, transform);
// jamesu - grab server object pose for debugging
OpenVRTrackedObject* tracked = static_cast<OpenVRTrackedObject*>(getServerObject());
if (tracked)
{
mPose = tracked->mPose;
}
ColorI drawColor = ColorI::GREEN;
if (!pose.valid)
{
drawColor = ColorI::RED;
}
// Draw Controller
MatrixF mat(1);
mPose.orientation.setMatrix(&mat);
mat.setPosition(mPose.position);
mat.inverse(); // same as HMD
mat = offsetMat * mat;
Point3F middleStart(0, -1 * CONTROLLER_SCALE, 0);
Point3F middleEnd(0, 1 * CONTROLLER_SCALE, 0);
Point3F middle(0, 0, 0);
Point3F center(0, 0, 0);
mat.mulP(center);
//DebugDrawer::get()->drawBox(center - Point3F(0.1), center + Point3F(0.1), ColorI::BLUE);
mat.mulP(middleStart);
mat.mulP(middle);
mat.mulP(middleEnd);
char buffer[256];
dSprintf(buffer, 256, "%f %f %f", center.x, center.y, center.z);
DebugDrawer::get()->drawText(middle, buffer);
DebugDrawer::get()->drawLine(middleStart, middle, ColorI(0, 255, 0)); // axis back
DebugDrawer::get()->drawLine(middleEnd, middle, ColorI(255, 0, 0)); // axis forward
DebugDrawer::get()->drawTransformedBoxOutline(Point3F(-0.5, -1, -0.5) * CONTROLLER_SCALE, Point3F(0.5, 1, 0.5) * CONTROLLER_SCALE, drawColor, mat); // general box
DebugDrawer::get()->drawBoxOutline(Point3F(-1), Point3F(1), ColorI::WHITE);
}
// Controller matrix base
MatrixF trackedMat = getTrackedTransform();
MatrixF invTrackedMat(1);
invTrackedMat = trackedMat;
invTrackedMat.inverse(); // -> world mat (as opposed to world -> tracked pos)
invTrackedMat = getBaseTrackingTransform() * invTrackedMat;
trackedMat = invTrackedMat;
trackedMat.inverse();
// Render the controllers, using either the render model or the shape
if (mShapeInstance)
{
// Calculate the distance of this object from the camera
Point3F cameraOffset = invTrackedMat.getPosition();
cameraOffset -= state->getDiffuseCameraPosition();
F32 dist = cameraOffset.len();
if (dist < 0.01f)
dist = 0.01f;
// Set up the LOD for the shape
F32 invScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
mShapeInstance->setDetailFromDistance(state, dist * invScale);
// Make sure we have a valid level of detail
if (mShapeInstance->getCurrentDetail() < 0)
return;
// GFXTransformSaver is a handy helper class that restores
// the current GFX matrices to their original values when
// it goes out of scope at the end of the function
GFXTransformSaver saver;
// Set up our TS render state
TSRenderState rdata;
rdata.setSceneState(state);
rdata.setFadeOverride(1.0f);
// We might have some forward lit materials
// so pass down a query to gather lights.
LightQuery query;
query.init(getWorldSphere());
rdata.setLightQuery(&query);
// Set the world matrix to the objects render transform
MatrixF mat = trackedMat;
mat.scale(mObjScale);
GFX->setWorldMatrix(mat);
// TODO: move the nodes about for components
mShapeInstance->animate();
mShapeInstance->render(rdata);
}
else if (mRenderComponents.size() > 0)
{
vr::IVRRenderModels *models = OPENVR->getRenderModels();
if (!models)
return;
vr::IVRSystem* vrs = vr::VRSystem();
if (!vrs->GetControllerState(mDeviceIndex, &mCurrentControllerState))
{
return;
}
for (U32 i = 0, sz = mRenderComponents.size(); i < sz; i++)
{
RenderModelSlot slot = mRenderComponents[i];
vr::RenderModel_ControllerMode_State_t modeState;
vr::RenderModel_ComponentState_t componentState;
modeState.bScrollWheelVisible = false;
if (models->GetComponentState(mModelName, slot.componentName, &mCurrentControllerState, &modeState, &componentState))
{
MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
// Set our RenderInst as a standard mesh render
ri->type = RenderPassManager::RIT_Mesh;
// Calculate our sorting point
if (state && slot.nativeModel)
{
// Calculate our sort point manually.
const Box3F rBox = slot.nativeModel->getWorldBox(invTrackedMat);
ri->sortDistSq = rBox.getSqDistanceToPoint(state->getCameraPosition());
}
else
{
ri->sortDistSq = 0.0f;
}
MatrixF newTransform = trackedMat;
MatrixF controllerOffsMat = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(componentState.mTrackingToComponentRenderModel);
MatrixF offComponentMat(1);
OpenVRUtil::convertTransformFromOVR(controllerOffsMat, offComponentMat);
newTransform = offComponentMat * newTransform;
newTransform.inverse();
//DebugDrawer::get()->drawBox(newTransform.getPosition() - Point3F(0.001), newTransform.getPosition() + Point3F(0.001), ColorI::BLUE);
if (!slot.nativeModel)
continue;
if (i < 1)
continue;
// Set up our transforms
ri->objectToWorld = renderPass->allocUniqueXform(newTransform);
ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection);
// If our material needs lights then fill the RIs
// light vector with the best lights.
if (true)
{
LightQuery query;
Point3F center(0, 0, 0);
invTrackedMat.mulP(center);
query.init(SphereF(center, 10.0f));
query.getLights(ri->lights, 8);
}
// Draw model
slot.nativeModel->draw(state, ri);
state->getRenderPass()->addInst(ri);
}
}
}
else if (mBasicModel)
{
MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
// Set our RenderInst as a standard mesh render
ri->type = RenderPassManager::RIT_Mesh;
// Calculate our sorting point
if (state)
{
// Calculate our sort point manually.
const Box3F rBox = mBasicModel->getWorldBox(invTrackedMat);
ri->sortDistSq = rBox.getSqDistanceToPoint(state->getCameraPosition());
}
else
{
ri->sortDistSq = 0.0f;
}
MatrixF newTransform = invTrackedMat;
// Set up our transforms
ri->objectToWorld = renderPass->allocUniqueXform(newTransform);
ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection);
// If our material needs lights then fill the RIs
// light vector with the best lights.
if (true)
{
LightQuery query;
Point3F center(0, 0, 0);
invTrackedMat.mulP(center);
query.init(SphereF(center, 10.0f));
query.getLights(ri->lights, 8);
}
// Draw model
mBasicModel->draw(state, ri);
state->getRenderPass()->addInst(ri);
}
}
U32 OpenVRTrackedObject::getCollisionMask()
{
2016-07-12 22:30:11 +00:00
if (isServerObject())
return sServerCollisionMask;
else
return sClientCollisionMask;
}
void OpenVRTrackedObject::updateWorkingCollisionSet()
{
2016-07-12 22:30:11 +00:00
const U32 mask = getCollisionMask();
Box3F convexBox = mConvexList->getBoundingBox(getTransform(), getScale());
F32 len = (50) * TickSec;
F32 l = (len * 1.1) + 0.1; // fudge factor
convexBox.minExtents -= Point3F(l, l, l);
convexBox.maxExtents += Point3F(l, l, l);
2016-07-12 22:30:11 +00:00
disableCollision();
mConvexList->updateWorkingList(convexBox, mask);
enableCollision();
}
void OpenVRTrackedObject::updateMove(const Move *move)
{
2016-07-12 22:30:11 +00:00
// Set transform based on move
#ifdef TORQUE_EXTENDED_MOVE
2016-07-12 22:30:11 +00:00
const ExtendedMove* emove = dynamic_cast<const ExtendedMove*>(move);
if (!emove)
return;
2016-07-12 22:30:11 +00:00
U32 emoveIndex = mMappedMoveIndex;
if (emoveIndex >= ExtendedMove::MaxPositionsRotations)
emoveIndex = 0;
2016-07-12 22:30:11 +00:00
//IDevicePose pose = OPENVR->getTrackedDevicePose(mDeviceIndex);
//Con::printf("OpenVRTrackedObject::processTick move %i", emoveIndex);
2016-07-12 22:30:11 +00:00
if (!emove->EulerBasedRotation[emoveIndex])
{
AngAxisF inRot = AngAxisF(Point3F(emove->rotX[emoveIndex], emove->rotY[emoveIndex], emove->rotZ[emoveIndex]), emove->rotW[emoveIndex]);
// Update our pose based on the move info
mPose.orientation = inRot;
mPose.position = Point3F(emove->posX[emoveIndex], emove->posY[emoveIndex], emove->posZ[emoveIndex]);
mPose.valid = true;
mPose.connected = true;
}
2016-07-12 22:30:11 +00:00
// Set transform based on move pose
MatrixF trackedMat(1);
MatrixF invTrackedMat(1);
2016-07-12 22:30:11 +00:00
mPose.orientation.setMatrix(&trackedMat);
trackedMat.setPosition(mPose.position);
2016-07-12 22:30:11 +00:00
invTrackedMat = trackedMat;
invTrackedMat.inverse(); // -> world mat (as opposed to world -> tracked pos)
2016-07-12 22:30:11 +00:00
invTrackedMat = getBaseTrackingTransform() * invTrackedMat;
trackedMat = invTrackedMat;
trackedMat.inverse();
2016-07-12 22:30:11 +00:00
SceneObject::setTransform(invTrackedMat);
2016-07-12 22:30:11 +00:00
if (mPhysicsRep)
mPhysicsRep->setTransform(invTrackedMat);
#endif
}
void OpenVRTrackedObject::processTick(const Move *move)
{
2016-07-12 22:30:11 +00:00
// Perform collision checks
if (isServerObject())
{
updateMove(move);
2016-07-12 22:30:11 +00:00
if (!mPhysicsRep)
{
updateWorkingCollisionSet();
}
}
2016-07-12 22:30:11 +00:00
Parent::processTick(move);
}
void OpenVRTrackedObject::interpolateTick(F32 delta)
{
2016-07-12 22:30:11 +00:00
// Set latest transform
2016-07-12 22:30:11 +00:00
Parent::interpolateTick(delta);
}
void OpenVRTrackedObject::advanceTime(F32 dt)
{
2016-07-12 22:30:11 +00:00
Parent::advanceTime(dt);
}
bool OpenVRTrackedObject::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
{
2016-07-12 22:30:11 +00:00
if (!mPose.connected || !mPose.valid)
return false;
// Collide against bounding box.
F32 st, et, fst = 0.0f, fet = 1.0f;
F32 *bmin = &mObjBox.minExtents.x;
F32 *bmax = &mObjBox.maxExtents.x;
F32 const *si = &start.x;
F32 const *ei = &end.x;
for (S32 i = 0; i < 3; i++) {
if (*si < *ei) {
if (*si > *bmax || *ei < *bmin)
return false;
F32 di = *ei - *si;
st = (*si < *bmin) ? (*bmin - *si) / di : 0.0f;
et = (*ei > *bmax) ? (*bmax - *si) / di : 1.0f;
}
else {
if (*ei > *bmax || *si < *bmin)
return false;
F32 di = *ei - *si;
st = (*si > *bmax) ? (*bmax - *si) / di : 0.0f;
et = (*ei < *bmin) ? (*bmin - *si) / di : 1.0f;
}
if (st > fst) fst = st;
if (et < fet) fet = et;
if (fet < fst)
return false;
bmin++; bmax++;
si++; ei++;
}
info->normal = start - end;
info->normal.normalizeSafe();
getTransform().mulV(info->normal);
info->t = fst;
info->object = this;
info->point.interpolate(start, end, fst);
info->material = 0;
return true;
}
void OpenVRTrackedObject::buildConvex(const Box3F& box, Convex* convex)
{
2016-07-12 22:30:11 +00:00
// These should really come out of a pool
mConvexList->collectGarbage();
Box3F realBox = box;
mWorldToObj.mul(realBox);
realBox.minExtents.convolveInverse(mObjScale);
realBox.maxExtents.convolveInverse(mObjScale);
if (realBox.isOverlapped(getObjBox()) == false)
return;
// Just return a box convex for the entire shape...
Convex* cc = 0;
CollisionWorkingList& wl = convex->getWorkingList();
for (CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext) {
if (itr->mConvex->getType() == BoxConvexType &&
itr->mConvex->getObject() == this) {
cc = itr->mConvex;
break;
}
}
if (cc)
return;
// Create a new convex.
BoxConvex* cp = new BoxConvex;
mConvexList->registerObject(cp);
convex->addToWorkingList(cp);
cp->init(this);
mObjBox.getCenter(&cp->mCenter);
cp->mSize.x = mObjBox.len_x() / 2.0f;
cp->mSize.y = mObjBox.len_y() / 2.0f;
cp->mSize.z = mObjBox.len_z() / 2.0f;
}
bool OpenVRTrackedObject::testObject(SceneObject* enter)
{
2016-07-12 22:30:11 +00:00
return false; // TODO
}
DefineEngineMethod(OpenVRTrackedObject, setModelName, void, (String modelName),, "Set model name. Typically you should do this from the client to update the server representation.")
{
2016-07-12 22:30:11 +00:00
object->setModelName(modelName);
}