2012-09-19 15:15:01 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
|
|
|
//
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to
|
|
|
|
|
// deal in the Software without restriction, including without limitation the
|
|
|
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
//
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
|
//
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
// IN THE SOFTWARE.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#include "platform/platform.h"
|
|
|
|
|
#include "T3D/gameFunctions.h"
|
|
|
|
|
#include "T3D/gameBase/gameConnection.h"
|
|
|
|
|
#include "T3D/camera.h"
|
|
|
|
|
#include "T3D/sfx/sfx3DWorld.h"
|
|
|
|
|
#include "console/consoleTypes.h"
|
|
|
|
|
#include "gui/3d/guiTSControl.h"
|
|
|
|
|
#include "core/util/journal/process.h"
|
|
|
|
|
#include "materials/materialManager.h"
|
|
|
|
|
#include "math/mEase.h"
|
|
|
|
|
#include "core/module.h"
|
|
|
|
|
#include "console/engineAPI.h"
|
2013-04-09 19:19:18 +00:00
|
|
|
#include "platform/output/IDisplayDevice.h"
|
2017-07-07 07:55:56 +00:00
|
|
|
#include "postFx/postEffectManager.h"
|
|
|
|
|
#include "gfx/gfxTransformSaver.h"
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
static void RegisterGameFunctions();
|
|
|
|
|
static void Process3D();
|
|
|
|
|
|
|
|
|
|
MODULE_BEGIN( 3D )
|
|
|
|
|
|
|
|
|
|
MODULE_INIT_AFTER( Process )
|
|
|
|
|
MODULE_INIT_AFTER( Scene )
|
|
|
|
|
|
|
|
|
|
MODULE_SHUTDOWN_BEFORE( Process )
|
|
|
|
|
MODULE_SHUTDOWN_BEFORE( Sim )
|
2021-11-02 22:52:54 +00:00
|
|
|
MODULE_SHUTDOWN_BEFORE( Scene )
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
MODULE_INIT
|
|
|
|
|
{
|
|
|
|
|
Process::notify(Process3D, PROCESS_TIME_ORDER);
|
|
|
|
|
|
|
|
|
|
GameConnection::smFovUpdate.notify(GameSetCameraFov);
|
|
|
|
|
|
|
|
|
|
RegisterGameFunctions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MODULE_SHUTDOWN
|
|
|
|
|
{
|
|
|
|
|
GameConnection::smFovUpdate.remove(GameSetCameraFov);
|
|
|
|
|
|
|
|
|
|
Process::remove(Process3D);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MODULE_END;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static S32 gEaseInOut = Ease::InOut;
|
|
|
|
|
static S32 gEaseIn = Ease::In;
|
|
|
|
|
static S32 gEaseOut = Ease::Out;
|
|
|
|
|
|
|
|
|
|
static S32 gEaseLinear = Ease::Linear;
|
|
|
|
|
static S32 gEaseQuadratic= Ease::Quadratic;
|
|
|
|
|
static S32 gEaseCubic= Ease::Cubic;
|
|
|
|
|
static S32 gEaseQuartic = Ease::Quartic;
|
|
|
|
|
static S32 gEaseQuintic = Ease::Quintic;
|
|
|
|
|
static S32 gEaseSinusoidal= Ease::Sinusoidal;
|
|
|
|
|
static S32 gEaseExponential = Ease::Exponential;
|
|
|
|
|
static S32 gEaseCircular = Ease::Circular;
|
|
|
|
|
static S32 gEaseElastic = Ease::Elastic;
|
|
|
|
|
static S32 gEaseBack = Ease::Back;
|
|
|
|
|
static S32 gEaseBounce = Ease::Bounce;
|
|
|
|
|
|
|
|
|
|
|
2013-04-09 19:19:18 +00:00
|
|
|
extern bool gEditingMission;
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
extern void ShowInit();
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
/// Camera and FOV info
|
2014-11-04 03:42:51 +00:00
|
|
|
namespace CameraAndFOV{
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
const U32 MaxZoomSpeed = 2000; ///< max number of ms to reach target FOV
|
|
|
|
|
|
|
|
|
|
static F32 sConsoleCameraFov = 90.f; ///< updated to camera FOV each frame
|
|
|
|
|
static F32 sDefaultFov = 90.f; ///< normal FOV
|
|
|
|
|
static F32 sCameraFov = 90.f; ///< current camera FOV
|
|
|
|
|
static F32 sTargetFov = 90.f; ///< the desired FOV
|
|
|
|
|
static F32 sLastCameraUpdateTime = 0; ///< last time camera was updated
|
|
|
|
|
static S32 sZoomSpeed = 500; ///< ms per 90deg fov change
|
|
|
|
|
|
|
|
|
|
/// A scale to apply to the normal visible distance
|
|
|
|
|
/// typically used for tuning performance.
|
|
|
|
|
static F32 sVisDistanceScale = 1.0f;
|
|
|
|
|
|
|
|
|
|
} // namespace {}
|
|
|
|
|
|
|
|
|
|
// query
|
|
|
|
|
static SimpleQueryList sgServerQueryList;
|
|
|
|
|
static U32 sgServerQueryIndex = 0;
|
|
|
|
|
|
|
|
|
|
//SERVER FUNCTIONS ONLY
|
|
|
|
|
ConsoleFunctionGroupBegin( Containers, "Spatial query functions. <b>Server side only!</b>");
|
|
|
|
|
|
2018-04-17 14:33:56 +00:00
|
|
|
DefineEngineFunction( containerFindFirst, const char*, (U32 typeMask, Point3F origin, Point3F size), , "(int mask, Point3F point, float x, float y, float z)"
|
2012-09-19 15:15:01 +00:00
|
|
|
"@brief Find objects matching the bitmask type within a box centered at point, with extents x, y, z.\n\n"
|
|
|
|
|
"@returns The first object found, or an empty string if nothing was found. Thereafter, you can get more "
|
|
|
|
|
"results using containerFindNext()."
|
|
|
|
|
"@see containerFindNext\n"
|
|
|
|
|
"@ingroup Game")
|
|
|
|
|
{
|
|
|
|
|
//find out what we're looking for
|
|
|
|
|
|
|
|
|
|
//build the container volume
|
|
|
|
|
Box3F queryBox;
|
|
|
|
|
queryBox.minExtents = origin;
|
|
|
|
|
queryBox.maxExtents = origin;
|
|
|
|
|
queryBox.minExtents -= size;
|
|
|
|
|
queryBox.maxExtents += size;
|
|
|
|
|
|
|
|
|
|
//initialize the list, and do the query
|
|
|
|
|
sgServerQueryList.mList.clear();
|
|
|
|
|
gServerContainer.findObjects(queryBox, typeMask, SimpleQueryList::insertionCallback, &sgServerQueryList);
|
|
|
|
|
|
|
|
|
|
//return the first element
|
|
|
|
|
sgServerQueryIndex = 0;
|
2014-05-15 07:12:43 +00:00
|
|
|
static const U32 bufSize = 100;
|
|
|
|
|
char *buff = Con::getReturnBuffer(bufSize);
|
2012-09-19 15:15:01 +00:00
|
|
|
if (sgServerQueryList.mList.size())
|
2014-05-15 07:12:43 +00:00
|
|
|
dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
buff[0] = '\0';
|
|
|
|
|
|
|
|
|
|
return buff;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:33:56 +00:00
|
|
|
DefineEngineFunction( containerFindNext, const char*, (), , "()"
|
2012-09-19 15:15:01 +00:00
|
|
|
"@brief Get more results from a previous call to containerFindFirst().\n\n"
|
|
|
|
|
"@note You must call containerFindFirst() to begin the search.\n"
|
|
|
|
|
"@returns The next object found, or an empty string if nothing else was found.\n"
|
|
|
|
|
"@see containerFindFirst()\n"
|
|
|
|
|
"@ingroup Game")
|
|
|
|
|
{
|
|
|
|
|
//return the next element
|
2014-05-15 07:12:43 +00:00
|
|
|
static const U32 bufSize = 100;
|
|
|
|
|
char *buff = Con::getReturnBuffer(bufSize);
|
2012-09-19 15:15:01 +00:00
|
|
|
if (sgServerQueryIndex < sgServerQueryList.mList.size())
|
2014-05-15 07:12:43 +00:00
|
|
|
dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
buff[0] = '\0';
|
|
|
|
|
|
|
|
|
|
return buff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConsoleFunctionGroupEnd( Containers );
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool GameGetCameraTransform(MatrixF *mat, Point3F *velocity)
|
|
|
|
|
{
|
|
|
|
|
// Return the position and velocity of the control object
|
|
|
|
|
GameConnection* connection = GameConnection::getConnectionToServer();
|
|
|
|
|
return connection && connection->getControlCameraTransform(0, mat) &&
|
|
|
|
|
connection->getControlCameraVelocity(velocity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
DefineEngineFunction( setDefaultFov, void, ( F32 defaultFOV ),,
|
|
|
|
|
"@brief Set the default FOV for a camera.\n"
|
|
|
|
|
"@param defaultFOV The default field of view in degrees\n"
|
|
|
|
|
"@ingroup CameraSystem")
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sDefaultFov = mClampF(defaultFOV, MinCameraFov, MaxCameraFov);
|
|
|
|
|
if(CameraAndFOV::sCameraFov == CameraAndFOV::sTargetFov)
|
|
|
|
|
CameraAndFOV::sTargetFov = CameraAndFOV::sDefaultFov;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DefineEngineFunction( setZoomSpeed, void, ( S32 speed ),,
|
|
|
|
|
"@brief Set the zoom speed of the camera.\n"
|
|
|
|
|
"This affects how quickly the camera changes from one field of view "
|
|
|
|
|
"to another.\n"
|
|
|
|
|
"@param speed The camera's zoom speed in ms per 90deg FOV change\n"
|
|
|
|
|
"@ingroup CameraSystem")
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sZoomSpeed = mClamp(speed, 0, CameraAndFOV::MaxZoomSpeed);
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DefineEngineFunction( setFov, void, ( F32 FOV ),,
|
|
|
|
|
"@brief Set the FOV of the camera.\n"
|
|
|
|
|
"@param FOV The camera's new FOV in degrees\n"
|
|
|
|
|
"@ingroup CameraSystem")
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sTargetFov = mClampF(FOV, MinCameraFov, MaxCameraFov);
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
F32 GameGetCameraFov()
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
return(CameraAndFOV::sCameraFov);
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameSetCameraFov(F32 fov)
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sTargetFov = CameraAndFOV::sCameraFov = fov;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameSetCameraTargetFov(F32 fov)
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sTargetFov = fov;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameUpdateCameraFov()
|
|
|
|
|
{
|
|
|
|
|
F32 time = F32(Platform::getVirtualMilliseconds());
|
|
|
|
|
|
|
|
|
|
// need to update fov?
|
2014-11-04 03:42:51 +00:00
|
|
|
if(CameraAndFOV::sTargetFov != CameraAndFOV::sCameraFov)
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
F32 delta = time - CameraAndFOV::sLastCameraUpdateTime;
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// snap zoom?
|
2015-01-29 10:17:38 +00:00
|
|
|
if((CameraAndFOV::sZoomSpeed == 0) || (delta <= 0.0f))
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sCameraFov = CameraAndFOV::sTargetFov;
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// gZoomSpeed is time in ms to zoom 90deg
|
2014-11-04 03:42:51 +00:00
|
|
|
F32 step = 90.f * (delta / F32(CameraAndFOV::sZoomSpeed));
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-11-04 03:42:51 +00:00
|
|
|
if(CameraAndFOV::sCameraFov > CameraAndFOV::sTargetFov)
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sCameraFov -= step;
|
|
|
|
|
if(CameraAndFOV::sCameraFov < CameraAndFOV::sTargetFov)
|
|
|
|
|
CameraAndFOV::sCameraFov = CameraAndFOV::sTargetFov;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sCameraFov += step;
|
|
|
|
|
if(CameraAndFOV::sCameraFov > CameraAndFOV::sTargetFov)
|
|
|
|
|
CameraAndFOV::sCameraFov = CameraAndFOV::sTargetFov;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// the game connection controls the vertical and the horizontal
|
|
|
|
|
GameConnection * connection = GameConnection::getConnectionToServer();
|
|
|
|
|
if(connection)
|
|
|
|
|
{
|
|
|
|
|
// check if fov is valid on control object
|
2014-11-04 03:42:51 +00:00
|
|
|
if(connection->isValidControlCameraFov(CameraAndFOV::sCameraFov))
|
|
|
|
|
connection->setControlCameraFov(CameraAndFOV::sCameraFov);
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// will set to the closest fov (fails only on invalid control object)
|
2014-11-04 03:42:51 +00:00
|
|
|
if(connection->setControlCameraFov(CameraAndFOV::sCameraFov))
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
F32 setFov = CameraAndFOV::sCameraFov;
|
2012-09-19 15:15:01 +00:00
|
|
|
connection->getControlCameraFov(&setFov);
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sTargetFov =CameraAndFOV::sCameraFov = setFov;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// update the console variable
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sConsoleCameraFov = CameraAndFOV::sCameraFov;
|
|
|
|
|
CameraAndFOV::sLastCameraUpdateTime = time;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#ifdef TORQUE_DEBUG
|
|
|
|
|
// ConsoleFunction(dumpTSShapes, void, 1, 1, "dumpTSShapes();")
|
|
|
|
|
// {
|
|
|
|
|
// argc, argv;
|
|
|
|
|
|
|
|
|
|
// FindMatch match("*.dts", 4096);
|
|
|
|
|
// gResourceManager->findMatches(&match);
|
|
|
|
|
|
|
|
|
|
// for (U32 i = 0; i < match.numMatches(); i++)
|
|
|
|
|
// {
|
|
|
|
|
// U32 j;
|
|
|
|
|
// Resource<TSShape> shape = ResourceManager::get().load(match.matchList[i]);
|
|
|
|
|
// if (bool(shape) == false)
|
|
|
|
|
// Con::errorf(" aaa Couldn't load: %s", match.matchList[i]);
|
|
|
|
|
|
|
|
|
|
// U32 numMeshes = 0, numSkins = 0;
|
|
|
|
|
// for (j = 0; j < shape->meshes.size(); j++)
|
|
|
|
|
// if (shape->meshes[j])
|
|
|
|
|
// numMeshes++;
|
|
|
|
|
// for (j = 0; j < shape->skins.size(); j++)
|
|
|
|
|
// if (shape->skins[j])
|
|
|
|
|
// numSkins++;
|
|
|
|
|
|
|
|
|
|
// Con::printf(" aaa Shape: %s (%d meshes, %d skins)", match.matchList[i], numMeshes, numSkins);
|
|
|
|
|
// Con::printf(" aaa Meshes");
|
|
|
|
|
// for (j = 0; j < shape->meshes.size(); j++)
|
|
|
|
|
// {
|
|
|
|
|
// if (shape->meshes[j])
|
|
|
|
|
// Con::printf(" aaa %d -> nf: %d, nmf: %d, nvpf: %d (%d, %d, %d, %d, %d)",
|
|
|
|
|
// shape->meshes[j]->meshType & TSMesh::TypeMask,
|
|
|
|
|
// shape->meshes[j]->numFrames,
|
|
|
|
|
// shape->meshes[j]->numMatFrames,
|
|
|
|
|
// shape->meshes[j]->vertsPerFrame,
|
|
|
|
|
// shape->meshes[j]->verts.size(),
|
|
|
|
|
// shape->meshes[j]->norms.size(),
|
|
|
|
|
// shape->meshes[j]->tverts.size(),
|
|
|
|
|
// shape->meshes[j]->primitives.size(),
|
|
|
|
|
// shape->meshes[j]->indices.size());
|
|
|
|
|
// }
|
|
|
|
|
// Con::printf(" aaa Skins");
|
|
|
|
|
// for (j = 0; j < shape->skins.size(); j++)
|
|
|
|
|
// {
|
|
|
|
|
// if (shape->skins[j])
|
|
|
|
|
// Con::printf(" aaa %d -> nf: %d, nmf: %d, nvpf: %d (%d, %d, %d, %d, %d)",
|
|
|
|
|
// shape->skins[j]->meshType & TSMesh::TypeMask,
|
|
|
|
|
// shape->skins[j]->numFrames,
|
|
|
|
|
// shape->skins[j]->numMatFrames,
|
|
|
|
|
// shape->skins[j]->vertsPerFrame,
|
|
|
|
|
// shape->skins[j]->verts.size(),
|
|
|
|
|
// shape->skins[j]->norms.size(),
|
|
|
|
|
// shape->skins[j]->tverts.size(),
|
|
|
|
|
// shape->skins[j]->primitives.size(),
|
|
|
|
|
// shape->skins[j]->indices.size());
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
bool GameProcessCameraQuery(CameraQuery *query)
|
|
|
|
|
{
|
|
|
|
|
GameConnection* connection = GameConnection::getConnectionToServer();
|
|
|
|
|
|
|
|
|
|
if (connection && connection->getControlCameraTransform(0.032f, &query->cameraMatrix))
|
|
|
|
|
{
|
2016-05-30 08:13:19 +00:00
|
|
|
query->object = dynamic_cast<GameBase*>(connection->getCameraObject());
|
2012-09-19 15:15:01 +00:00
|
|
|
query->nearPlane = gClientSceneGraph->getNearClip();
|
|
|
|
|
|
|
|
|
|
// Scale the normal visible distance by the performance
|
|
|
|
|
// tuning scale which we never let over 1.
|
2014-11-04 03:42:51 +00:00
|
|
|
CameraAndFOV::sVisDistanceScale = mClampF( CameraAndFOV::sVisDistanceScale, 0.01f, 1.0f );
|
|
|
|
|
query->farPlane = gClientSceneGraph->getVisibleDistance() * CameraAndFOV::sVisDistanceScale;
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2013-04-09 19:19:18 +00:00
|
|
|
// Provide some default values
|
2015-06-21 19:59:41 +00:00
|
|
|
query->stereoTargets[0] = 0;
|
|
|
|
|
query->stereoTargets[1] = 0;
|
|
|
|
|
query->eyeOffset[0] = Point3F::Zero;
|
|
|
|
|
query->eyeOffset[1] = Point3F::Zero;
|
|
|
|
|
query->hasFovPort = false;
|
|
|
|
|
query->hasStereoTargets = false;
|
2016-04-17 21:19:42 +00:00
|
|
|
query->displayDevice = NULL;
|
2015-06-21 19:59:41 +00:00
|
|
|
|
2013-04-09 19:19:18 +00:00
|
|
|
F32 cameraFov = 0.0f;
|
|
|
|
|
bool fovSet = false;
|
|
|
|
|
|
|
|
|
|
// Try to use the connection's display deivce, if any, but only if the editor
|
|
|
|
|
// is not open
|
|
|
|
|
if(!gEditingMission && connection->hasDisplayDevice())
|
|
|
|
|
{
|
2015-05-06 22:07:48 +00:00
|
|
|
IDisplayDevice* display = connection->getDisplayDevice();
|
2016-04-17 21:19:42 +00:00
|
|
|
|
|
|
|
|
query->displayDevice = display;
|
|
|
|
|
|
2015-05-06 22:07:48 +00:00
|
|
|
// Note: all eye values are invalid until this is called
|
|
|
|
|
display->setDrawCanvas(query->drawCanvas);
|
2013-04-09 19:19:18 +00:00
|
|
|
|
2015-05-06 22:07:48 +00:00
|
|
|
display->setCurrentConnection(connection);
|
|
|
|
|
|
|
|
|
|
// Display may activate AFTER so we need to call this again just in case
|
|
|
|
|
display->onStartFrame();
|
2013-04-09 19:19:18 +00:00
|
|
|
|
|
|
|
|
// The connection's display device may want to set the eye offset
|
2015-05-06 22:07:48 +00:00
|
|
|
if(display->providesEyeOffsets())
|
2013-04-09 19:19:18 +00:00
|
|
|
{
|
2015-05-06 22:07:48 +00:00
|
|
|
display->getEyeOffsets(query->eyeOffset);
|
2013-04-09 19:19:18 +00:00
|
|
|
}
|
2015-05-06 22:07:48 +00:00
|
|
|
|
|
|
|
|
// Grab field of view for both eyes
|
|
|
|
|
if (display->providesFovPorts())
|
|
|
|
|
{
|
|
|
|
|
display->getFovPorts(query->fovPort);
|
|
|
|
|
fovSet = true;
|
2015-06-21 19:59:41 +00:00
|
|
|
query->hasFovPort = true;
|
2015-05-06 22:07:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Grab the latest overriding render view transforms
|
|
|
|
|
connection->getControlCameraEyeTransforms(display, query->eyeTransforms);
|
2016-05-17 23:18:02 +00:00
|
|
|
connection->getControlCameraHeadTransform(display, &query->headMatrix);
|
2015-05-06 22:07:48 +00:00
|
|
|
|
|
|
|
|
display->getStereoViewports(query->stereoViewports);
|
|
|
|
|
display->getStereoTargets(query->stereoTargets);
|
2015-06-21 20:14:34 +00:00
|
|
|
query->hasStereoTargets = true;
|
2013-04-09 19:19:18 +00:00
|
|
|
}
|
2015-06-21 19:59:41 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query->eyeTransforms[0] = query->cameraMatrix;
|
|
|
|
|
query->eyeTransforms[1] = query->cameraMatrix;
|
2016-05-17 23:18:02 +00:00
|
|
|
query->headMatrix = query->cameraMatrix;
|
2015-06-21 19:59:41 +00:00
|
|
|
}
|
2013-04-09 19:19:18 +00:00
|
|
|
|
|
|
|
|
// Use the connection's FOV settings if requried
|
2015-05-06 22:07:48 +00:00
|
|
|
if(!connection->getControlCameraFov(&cameraFov))
|
2013-04-09 19:19:18 +00:00
|
|
|
{
|
2012-09-19 15:15:01 +00:00
|
|
|
return false;
|
2013-04-09 19:19:18 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
query->fov = mDegToRad(cameraFov);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameRenderWorld()
|
|
|
|
|
{
|
|
|
|
|
PROFILE_START(GameRenderWorld);
|
|
|
|
|
FrameAllocator::setWaterMark(0);
|
|
|
|
|
|
|
|
|
|
gClientSceneGraph->renderScene( SPT_Diffuse );
|
|
|
|
|
|
|
|
|
|
// renderScene leaves some states dirty, which causes problems if GameTSCtrl is the last Gui object rendered
|
|
|
|
|
GFX->updateStates();
|
|
|
|
|
|
|
|
|
|
AssertFatal(FrameAllocator::getWaterMark() == 0,
|
|
|
|
|
"Error, someone didn't reset the water mark on the frame allocator!");
|
|
|
|
|
FrameAllocator::setWaterMark(0);
|
|
|
|
|
PROFILE_END();
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-07 07:55:56 +00:00
|
|
|
//================================================================================================
|
|
|
|
|
//Render a full frame from a given transform and frustum, and render out to a target
|
|
|
|
|
//================================================================================================
|
|
|
|
|
void renderFrame(GFXTextureTargetRef* target, MatrixF transform, Frustum frustum, U32 typeMask, ColorI canvasClearColor)
|
|
|
|
|
{
|
|
|
|
|
if (!GFX->allowRender() || GFX->canCurrentlyRender())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
PROFILE_START(GameFunctions_RenderFrame);
|
|
|
|
|
|
|
|
|
|
GFX->setActiveRenderTarget(*target);
|
|
|
|
|
if (!GFX->getActiveRenderTarget())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
GFXTarget* renderTarget = GFX->getActiveRenderTarget();
|
|
|
|
|
if (renderTarget == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Make sure the root control is the size of the canvas.
|
|
|
|
|
Point2I size = renderTarget->getSize();
|
|
|
|
|
if (size.x == 0 || size.y == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//Now, getting to the meat of it!
|
|
|
|
|
#ifdef TORQUE_GFX_STATE_DEBUG
|
|
|
|
|
GFX->getDebugStateManager()->startFrame();
|
|
|
|
|
#endif
|
|
|
|
|
RectI targetRect(0, 0, size.x, size.y);
|
|
|
|
|
|
|
|
|
|
// Signal the interested parties.
|
|
|
|
|
GuiCanvas::getGuiCanvasFrameSignal().trigger(true);
|
|
|
|
|
|
|
|
|
|
GFXTransformSaver saver;
|
|
|
|
|
|
|
|
|
|
// Gross hack to make sure we don't end up with advanced lighting and msaa
|
|
|
|
|
// at the same time, which causes artifacts. At the same time we don't
|
|
|
|
|
// want to just throw the settings the user has chosen if the light manager
|
|
|
|
|
// changes at a later time.
|
|
|
|
|
/*GFXVideoMode mode = mPlatformWindow->getVideoMode();
|
|
|
|
|
if (dStricmp(LIGHTMGR->getId(), "ADVLM") == 0 && mode.antialiasLevel > 0)
|
|
|
|
|
{
|
|
|
|
|
const char *pref = Con::getVariable("$pref::Video::mode");
|
|
|
|
|
mode.parseFromString(pref);
|
|
|
|
|
mode.antialiasLevel = 0;
|
|
|
|
|
mPlatformWindow->setVideoMode(mode);
|
|
|
|
|
|
|
|
|
|
Con::printf("AntiAliasing has been disabled; it is not compatible with AdvancedLighting.");
|
|
|
|
|
}
|
|
|
|
|
else if (dStricmp(LIGHTMGR->getId(), "BLM") == 0)
|
|
|
|
|
{
|
|
|
|
|
const char *pref = Con::getVariable("$pref::Video::mode");
|
|
|
|
|
|
|
|
|
|
U32 prefAA = dAtoi(StringUnit::getUnit(pref, 5, " "));
|
|
|
|
|
if (prefAA != mode.antialiasLevel)
|
|
|
|
|
{
|
|
|
|
|
mode.parseFromString(pref);
|
|
|
|
|
mPlatformWindow->setVideoMode(mode);
|
|
|
|
|
|
|
|
|
|
Con::printf("AntiAliasing has been enabled while running BasicLighting.");
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
// Begin GFX
|
|
|
|
|
PROFILE_START(GameFunctions_RenderFrame_GFXBeginScene);
|
|
|
|
|
bool beginSceneRes = GFX->beginScene();
|
|
|
|
|
PROFILE_END();
|
|
|
|
|
|
|
|
|
|
PROFILE_START(GameFunctions_RenderFrame_OffscreenCanvases);
|
|
|
|
|
|
|
|
|
|
// Render all offscreen canvas objects here since we may need them in the render loop
|
|
|
|
|
if (GuiOffscreenCanvas::sList.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
// Reset the entire state since oculus shit will have barfed it.
|
|
|
|
|
GFX->updateStates(true);
|
|
|
|
|
|
|
|
|
|
for (Vector<GuiOffscreenCanvas*>::iterator itr = GuiOffscreenCanvas::sList.begin(); itr != GuiOffscreenCanvas::sList.end(); itr++)
|
|
|
|
|
{
|
|
|
|
|
(*itr)->renderFrame(false, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GFX->setActiveRenderTarget(renderTarget);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PROFILE_END();
|
|
|
|
|
|
|
|
|
|
// Can't render if waiting for device to reset.
|
|
|
|
|
if (!beginSceneRes)
|
|
|
|
|
{
|
|
|
|
|
// Since we already triggered the signal once for begin-of-frame,
|
|
|
|
|
// we should be consistent and trigger it again for end-of-frame.
|
|
|
|
|
GuiCanvas::getGuiCanvasFrameSignal().trigger(false);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear the current viewport area
|
|
|
|
|
GFX->setViewport(targetRect);
|
|
|
|
|
GFX->clear(GFXClearZBuffer | GFXClearStencil | GFXClearTarget, canvasClearColor, 1.0f, 0);
|
|
|
|
|
|
|
|
|
|
// Make sure we have a clean matrix state
|
|
|
|
|
// before we start rendering anything!
|
|
|
|
|
GFX->setWorldMatrix(MatrixF::Identity);
|
|
|
|
|
GFX->setViewMatrix(MatrixF::Identity);
|
|
|
|
|
GFX->setProjectionMatrix(MatrixF::Identity);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
GFXStateBlockDesc d;
|
|
|
|
|
|
|
|
|
|
d.cullDefined = true;
|
|
|
|
|
d.cullMode = GFXCullNone;
|
|
|
|
|
d.zDefined = true;
|
|
|
|
|
d.zEnable = false;
|
|
|
|
|
|
|
|
|
|
GFXStateBlockRef mDefaultGuiSB = GFX->createStateBlock(d);
|
|
|
|
|
|
|
|
|
|
GFX->setClipRect(targetRect);
|
|
|
|
|
GFX->setStateBlock(mDefaultGuiSB);
|
|
|
|
|
|
|
|
|
|
GFXTargetRef origTarget = GFX->getActiveRenderTarget();
|
|
|
|
|
|
|
|
|
|
// Clear the zBuffer so GUI doesn't hose object rendering accidentally
|
|
|
|
|
GFX->clear(GFXClearZBuffer, ColorI(20, 20, 20), 1.0f, 0);
|
|
|
|
|
|
|
|
|
|
GFX->setFrustum(frustum);
|
|
|
|
|
MatrixF mSaveProjection = GFX->getProjectionMatrix();
|
|
|
|
|
|
|
|
|
|
// We're going to be displaying this render at size of this control in
|
|
|
|
|
// pixels - let the scene know so that it can calculate e.g. reflections
|
|
|
|
|
// correctly for that final display result.
|
|
|
|
|
gClientSceneGraph->setDisplayTargetResolution(size);
|
|
|
|
|
|
|
|
|
|
// Set the GFX world matrix to the world-to-camera transform, but don't
|
|
|
|
|
// change the cameraMatrix in mLastCameraQuery. This is because
|
|
|
|
|
// mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world
|
|
|
|
|
// transform. In-place invert would save a copy but mess up any GUIs that
|
|
|
|
|
// depend on that value.
|
|
|
|
|
CameraQuery camera;
|
|
|
|
|
GameProcessCameraQuery(&camera);
|
|
|
|
|
|
|
|
|
|
MatrixF worldToCamera = transform;
|
|
|
|
|
|
|
|
|
|
RotationF tranRot = RotationF(transform);
|
|
|
|
|
EulerF trf = tranRot.asEulerF(RotationF::Degrees);
|
|
|
|
|
Point3F pos = transform.getPosition();
|
|
|
|
|
|
|
|
|
|
GFX->setWorldMatrix(worldToCamera);
|
|
|
|
|
|
|
|
|
|
mSaveProjection = GFX->getProjectionMatrix();
|
|
|
|
|
MatrixF mSaveModelview = GFX->getWorldMatrix();
|
|
|
|
|
|
|
|
|
|
Point2F mSaveWorldToScreenScale = GFX->getWorldToScreenScale();
|
|
|
|
|
Frustum mSaveFrustum = GFX->getFrustum();
|
|
|
|
|
mSaveFrustum.setTransform(transform);
|
|
|
|
|
|
|
|
|
|
// Set the default non-clip projection as some
|
|
|
|
|
// objects depend on this even in non-reflect cases.
|
|
|
|
|
gClientSceneGraph->setNonClipProjection(mSaveProjection);
|
|
|
|
|
|
|
|
|
|
// Give the post effect manager the worldToCamera, and cameraToScreen matrices
|
|
|
|
|
PFXMGR->setFrameMatrices(mSaveModelview, mSaveProjection);
|
|
|
|
|
|
|
|
|
|
//renderWorld(guiViewport);
|
|
|
|
|
PROFILE_START(GameFunctions_RenderFrame_RenderWorld);
|
|
|
|
|
FrameAllocator::setWaterMark(0);
|
|
|
|
|
|
|
|
|
|
gClientSceneGraph->renderScene(SPT_Reflect, typeMask);
|
|
|
|
|
|
|
|
|
|
// renderScene leaves some states dirty, which causes problems if GameTSCtrl is the last Gui object rendered
|
|
|
|
|
GFX->updateStates();
|
|
|
|
|
|
|
|
|
|
AssertFatal(FrameAllocator::getWaterMark() == 0,
|
|
|
|
|
"Error, someone didn't reset the water mark on the frame allocator!");
|
|
|
|
|
FrameAllocator::setWaterMark(0);
|
|
|
|
|
PROFILE_END();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PROFILE_START(GameFunctions_RenderFrame_GFXEndScene);
|
|
|
|
|
GFX->endScene();
|
|
|
|
|
PROFILE_END();
|
|
|
|
|
|
|
|
|
|
#ifdef TORQUE_GFX_STATE_DEBUG
|
|
|
|
|
GFX->getDebugStateManager()->endFrame();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
saver.restore();
|
|
|
|
|
|
|
|
|
|
PROFILE_END();
|
|
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2017-07-07 07:55:56 +00:00
|
|
|
//================================================================================================
|
2012-09-19 15:15:01 +00:00
|
|
|
static void Process3D()
|
|
|
|
|
{
|
|
|
|
|
MATMGR->updateTime();
|
|
|
|
|
|
|
|
|
|
// Update the SFX world, if there is one.
|
|
|
|
|
|
|
|
|
|
if( gSFX3DWorld )
|
|
|
|
|
gSFX3DWorld->update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void RegisterGameFunctions()
|
|
|
|
|
{
|
2014-11-04 03:42:51 +00:00
|
|
|
Con::addVariable( "$pref::Camera::distanceScale", TypeF32, &CameraAndFOV::sVisDistanceScale,
|
2012-09-19 15:15:01 +00:00
|
|
|
"A scale to apply to the normal visible distance, typically used for tuning performance.\n"
|
|
|
|
|
"@ingroup Game");
|
2014-11-04 03:42:51 +00:00
|
|
|
Con::addVariable( "$cameraFov", TypeF32, &CameraAndFOV::sConsoleCameraFov,
|
2012-09-19 15:15:01 +00:00
|
|
|
"The camera's Field of View.\n\n"
|
|
|
|
|
"@ingroup Game" );
|
|
|
|
|
|
|
|
|
|
// Stuff game types into the console
|
|
|
|
|
Con::setIntVariable("$TypeMasks::StaticObjectType", StaticObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::EnvironmentObjectType", EnvironmentObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::TerrainObjectType", TerrainObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::WaterObjectType", WaterObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::TriggerObjectType", TriggerObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::MarkerObjectType", MarkerObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::GameBaseObjectType", GameBaseObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::ShapeBaseObjectType", ShapeBaseObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::CameraObjectType", CameraObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::StaticShapeObjectType", StaticShapeObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::DynamicShapeObjectType", DynamicShapeObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::PlayerObjectType", PlayerObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::ItemObjectType", ItemObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::VehicleObjectType", VehicleObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::VehicleBlockerObjectType", VehicleBlockerObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::ProjectileObjectType", ProjectileObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::ExplosionObjectType", ExplosionObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::CorpseObjectType", CorpseObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::DebrisObjectType", DebrisObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::PhysicalZoneObjectType", PhysicalZoneObjectType);
|
|
|
|
|
Con::setIntVariable("$TypeMasks::LightObjectType", LightObjectType);
|
2020-01-12 05:58:30 +00:00
|
|
|
// PATHSHAPE
|
|
|
|
|
Con::setIntVariable("$TypeMasks::PathShapeObjectType", PathShapeObjectType);
|
|
|
|
|
// PATHSHAPE END
|
2021-11-11 00:20:03 +00:00
|
|
|
Con::setIntVariable("$TypeMasks::TurretObjectType", TurretObjectType);
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
Con::addVariable("Ease::InOut", TypeS32, &gEaseInOut,
|
|
|
|
|
"InOut ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::In", TypeS32, &gEaseIn,
|
|
|
|
|
"In ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Out", TypeS32, &gEaseOut,
|
|
|
|
|
"Out ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
|
|
|
|
|
Con::addVariable("Ease::Linear", TypeS32, &gEaseLinear,
|
|
|
|
|
"Linear ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Quadratic", TypeS32, &gEaseQuadratic,
|
|
|
|
|
"Quadratic ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Cubic", TypeS32, &gEaseCubic,
|
|
|
|
|
"Cubic ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Quartic", TypeS32, &gEaseQuartic,
|
|
|
|
|
"Quartic ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Quintic", TypeS32, &gEaseQuintic,
|
|
|
|
|
"Quintic ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Sinusoidal", TypeS32, &gEaseSinusoidal,
|
|
|
|
|
"Sinusoidal ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Exponential", TypeS32, &gEaseExponential,
|
|
|
|
|
"Exponential ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Circular", TypeS32, &gEaseCircular,
|
|
|
|
|
"Circular ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Elastic", TypeS32, &gEaseElastic,
|
|
|
|
|
"Elastic ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Back", TypeS32, &gEaseBack,
|
|
|
|
|
"Backwards ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
Con::addVariable("Ease::Bounce", TypeS32, &gEaseBounce,
|
|
|
|
|
"Bounce ease for curve movement.\n"
|
|
|
|
|
"@ingroup Game");
|
|
|
|
|
}
|