/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of HPL1 Engine. */ #include "hpl1/engine/haptic/LowLevelHaptic.h" #include "hpl1/engine/haptic/HapticForce.h" #include "hpl1/engine/haptic/HapticShape.h" #include "hpl1/engine/haptic/HapticSurface.h" #include "hpl1/engine/system/low_level_system.h" #include "hpl1/engine/system/SystemTypes.h" #include "hpl1/engine/math/Math.h" #include "hpl1/engine/physics/PhysicsBody.h" #include "hpl1/engine/scene/Camera3D.h" #include "hpl1/engine/scene/SubMeshEntity.h" namespace hpl { ////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- iLowLevelHaptic::iLowLevelHaptic() { mpCamera = NULL; mvCameraOffset = 0; mvMinMousePos = cVector2f(-50, -50); mvMaxMousePos = cVector2f(50, 50); mvScreenSize = cVector2f(800, 600); mbUpdateShapes = true; } //----------------------------------------------------------------------- iLowLevelHaptic::~iLowLevelHaptic() { } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- iHapticSurface *iLowLevelHaptic::GetSurfaceFromName(const tString &asName) { tHapticSurfaceMapIt it = m_mapSurfaces.find(asName); if (it == m_mapSurfaces.end()) { return NULL; } iHapticSurface *pSurface = it->second; return pSurface; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- bool iLowLevelHaptic::Init(cResources *apResources) { mpResources = apResources; if (InitLowLevel() == false) return false; ///////////////////////////////////// // Init variables mvCurrentHardwarePos = GetHardwarePosition(); mvPreviousHardwarePos = mvCurrentHardwarePos; mbScreenPosFirstTime = true; return true; } //----------------------------------------------------------------------- void iLowLevelHaptic::Update(float afTimeStep) { UpdateLowLevel(afTimeStep); ///////////////////////////////////// // Hardware position calculations static bool bHardwareSet = false; mvPreviousHardwarePos = mvCurrentHardwarePos; mvCurrentHardwarePos = GetHardwarePosition(); if (bHardwareSet == false) { mvPreviousHardwarePos = mvCurrentHardwarePos; bHardwareSet = true; } ///////////////////////////////////// // Proxy screen postion calculations if (mpCamera) { mvPreviousScreenPos = mvCurrentScreenPos; cVector3f vProjPos = cMath::MatrixMul(mpCamera->GetViewMatrix(), GetProxyPosition()); vProjPos = cMath::MatrixMulDivideW(mpCamera->GetProjectionMatrix(), vProjPos); cVector2f vPos2D((vProjPos.x + 1) * 0.5f, (-vProjPos.y + 1) * 0.5f); mvCurrentScreenPos = vPos2D; if (mbScreenPosFirstTime) { mvPreviousScreenPos = mvCurrentScreenPos; mbScreenPosFirstTime = false; } } ///////////////////////////////////// // Update shape transforms if (mbUpdateShapes) { tHapticShapeListIt it = mlstShapes.begin(); for (; it != mlstShapes.end(); ++it) { iHapticShape *pShape = *it; // If a body is attached, use it to update shape if (pShape->GetBody()) { iPhysicsBody *pBody = pShape->GetBody(); if (pBody->GetTransformUpdateCount() != pShape->GetTransformCount()) { pShape->SetTransformCount(pBody->GetTransformUpdateCount()); pShape->SetTransform(pBody->GetLocalMatrix()); } } else if (pShape->GetSubMeshEntity()) { cSubMeshEntity *pSubEntity = pShape->GetSubMeshEntity(); if (pSubEntity->GetTransformUpdateCount() != pShape->GetTransformCount()) { pShape->SetTransformCount(pSubEntity->GetTransformUpdateCount()); pShape->SetTransform(pSubEntity->GetWorldMatrix()); } } } } } //----------------------------------------------------------------------- cVector3f iLowLevelHaptic::GetHardwarePosDelta() { return mvCurrentHardwarePos - mvPreviousHardwarePos; } //----------------------------------------------------------------------- cVector2f iLowLevelHaptic::GetProxyScreenPos(const cVector2f &avScreenSize) { return mvCurrentScreenPos * avScreenSize; } cVector2f iLowLevelHaptic::GetProxyScreenDeltaPos(const cVector2f &avScreenSize) { return (mvCurrentScreenPos - mvPreviousScreenPos) * avScreenSize; } //----------------------------------------------------------------------- cVector2f iLowLevelHaptic::GetRelativeVirtualMousePos() { cVector3f vRel = GetHardwarePosDelta(); cVector2f vPos = cVector2f(vRel.x, vRel.y) / (mvMaxMousePos - mvMinMousePos); vPos.y = -vPos.y; vPos = vPos * mvScreenSize; return vPos; } //----------------------------------------------------------------------- cVector2f iLowLevelHaptic::GetVirtualMousePos() { // Log("Pos: %f %f\n", mvCurrentHardwarePos.x,mvCurrentHardwarePos.y); cVector2f vPos = (cVector2f(mvCurrentHardwarePos.x, mvCurrentHardwarePos.y) - mvMinMousePos) / (mvMaxMousePos - mvMinMousePos); vPos.y = 1 - vPos.y; vPos = vPos * mvScreenSize; return vPos; } void iLowLevelHaptic::SetVirtualMousePosBounds(const cVector2f &avMin, const cVector2f &avMax, const cVector2f &avScreenSize) { mvMinMousePos = avMin; mvMaxMousePos = avMax; mvScreenSize = avScreenSize; } //----------------------------------------------------------------------- void iLowLevelHaptic::DestroyShape(iHapticShape *apShape) { STLFindAndDelete(mlstShapes, apShape); } bool iLowLevelHaptic::ShapeExists(iHapticShape *apShape) { tHapticShapeListIt it = mlstShapes.begin(); for (; it != mlstShapes.end(); ++it) { if (apShape == *it) return true; } return false; } //----------------------------------------------------------------------- cHapticShapeIterator iLowLevelHaptic::GetShapeIterator() { return cHapticShapeIterator(&mlstShapes); } //----------------------------------------------------------------------- void iLowLevelHaptic::DestroyForce(iHapticForce *apForce) { STLFindAndDelete(mlstForces, apForce); } //----------------------------------------------------------------------- void iLowLevelHaptic::StopAllForces() { tHapticForceListIt it = mlstForces.begin(); for (; it != mlstForces.end(); ++it) { iHapticForce *pForce = *it; pForce->SetActive(false); } } //----------------------------------------------------------------------- void iLowLevelHaptic::DestroyAllShapes() { STLDeleteAll(mlstShapes); // Log("Destroying all shapes!\n"); } void iLowLevelHaptic::DestroyAll() { STLMapDeleteAll(m_mapSurfaces); STLDeleteAll(mlstForces); STLDeleteAll(mlstShapes); } //----------------------------------------------------------------------- } // namespace hpl