📄 sceneobject.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "sim/sceneObject.h"
#include "sceneGraph/sceneGraph.h"
#include "console/consoleTypes.h"
#include "collision/extrudedPolyList.h"
#include "collision/earlyOutPolyList.h"
#include "platform/profiler.h"
#include "platform/profiler.h"
#include "interior/interior.h"
#include "interior/interiorInstance.h"
#include "terrain/terrData.h"
#include "dgl/gBitmap.h"
#include "dgl/dgl.h"
IMPLEMENT_CONOBJECT(SceneObject);
const U32 Container::csmNumBins = 16;
const F32 Container::csmBinSize = 64;
const F32 Container::csmTotalBinSize = Container::csmBinSize * Container::csmNumBins;
U32 Container::smCurrSeqKey = 1;
const U32 Container::csmRefPoolBlockSize = 4096;
// Statics used by buildPolyList methods
AbstractPolyList* sPolyList;
SphereF sBoundingSphere;
Box3F sBoundingBox;
// Statics used by collide methods
ExtrudedPolyList sExtrudedPolyList;
Polyhedron sBoxPolyhedron;
//--------------------------------------------------------------------------
//-------------------------------------- Console callbacks
//
ConsoleMethod( SceneObject, getTransform, const char*, 2, 2, "Get transform of object.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const MatrixF& mat = object->getTransform();
Point3F pos;
mat.getColumn(3,&pos);
AngAxisF aa(mat);
dSprintf(returnBuffer,256,"%g %g %g %g %g %g %g",
pos.x,pos.y,pos.z,aa.axis.x,aa.axis.y,aa.axis.z,aa.angle);
return returnBuffer;
}
ConsoleMethod( SceneObject, getPosition, const char*, 2, 2, "Get position of object.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const MatrixF& mat = object->getTransform();
Point3F pos;
mat.getColumn(3,&pos);
dSprintf(returnBuffer,256,"%g %g %g",pos.x,pos.y,pos.z);
return returnBuffer;
}
ConsoleMethod( SceneObject, getForwardVector, const char*, 2, 2, "Returns a vector indicating the direction this object is facing.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const MatrixF& mat = object->getTransform();
Point3F dir;
mat.getColumn(1,&dir);
dSprintf(returnBuffer,256,"%g %g %g",dir.x,dir.y,dir.z);
return returnBuffer;
}
ConsoleMethod( SceneObject, setTransform, void, 3, 3, "(Transform T)")
{
Point3F pos;
const MatrixF& tmat = object->getTransform();
tmat.getColumn(3,&pos);
AngAxisF aa(tmat);
dSscanf(argv[2],"%g %g %g %g %g %g %g",
&pos.x,&pos.y,&pos.z,&aa.axis.x,&aa.axis.y,&aa.axis.z,&aa.angle);
MatrixF mat;
aa.setMatrix(&mat);
mat.setColumn(3,pos);
object->setTransform(mat);
}
ConsoleMethod( SceneObject, getScale, const char*, 2, 2, "Get scaling as a Point3F.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const VectorF & scale = object->getScale();
dSprintf(returnBuffer, 256, "%g %g %g",
scale.x, scale.y, scale.z);
return(returnBuffer);
}
ConsoleMethod( SceneObject, setScale, void, 3, 3, "(Point3F scale)")
{
VectorF scale(0.f,0.f,0.f);
dSscanf(argv[2], "%g %g %g", &scale.x, &scale.y, &scale.z);
object->setScale(scale);
}
ConsoleMethod( SceneObject, getWorldBox, const char*, 2, 2, "Returns six fields, two Point3Fs, containing the min and max points of the worldbox.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const Box3F& box = object->getWorldBox();
dSprintf(returnBuffer,256,"%g %g %g %g %g %g",
box.min.x, box.min.y, box.min.z,
box.max.x, box.max.y, box.max.z);
return returnBuffer;
}
ConsoleMethod( SceneObject, getWorldBoxCenter, const char*, 2, 2, "Returns the center of the world bounding box.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const Box3F& box = object->getWorldBox();
Point3F center;
box.getCenter(¢er);
dSprintf(returnBuffer,256,"%g %g %g", center.x, center.y, center.z);
return returnBuffer;
}
ConsoleMethod( SceneObject, getObjectBox, const char *, 2, 2, "Returns the bounding box relative to the object's origin.")
{
char *returnBuffer = Con::getReturnBuffer(256);
const Box3F& box = object->getObjBox();
dSprintf(returnBuffer,256,"%g %g %g %g %g %g",
box.min.x, box.min.y, box.min.z,
box.max.x, box.max.y, box.max.z);
return returnBuffer;
}
ConsoleFunctionGroupBegin( Containers, "Functions for ray casting and spatial queries.\n\n"
"@note These only work server-side.");
ConsoleFunction(containerBoxEmpty, bool, 4, 6, "(bitset mask, Point3F center, float xRadius, float yRadius, float zRadius)"
"See if any objects of given types are present in box of given extent.\n\n"
"@note Extent parameter is last since only one radius is often needed. If one radius is provided, "
"the yRadius and zRadius are assumed to be the same.\n"
"@param mask Indicates the type of objects we are checking against.\n"
"@param center Center of box.\n"
"@param xRadius See above.\n"
"@param yRadius See above.\n"
"@param zRadius See above.")
{
Point3F center;
Point3F extent;
U32 mask = dAtoi(argv[1]);
dSscanf(argv[2], "%g %g %g", ¢er.x, ¢er.y, ¢er.z);
extent.x = dAtof(argv[3]);
extent.y = argc > 4 ? dAtof(argv[4]) : extent.x;
extent.z = argc > 5 ? dAtof(argv[5]) : extent.x;
Box3F B(center - extent, center + extent, true);
EarlyOutPolyList polyList;
polyList.mPlaneList.clear();
polyList.mNormal.set(0,0,0);
polyList.mPlaneList.setSize(6);
polyList.mPlaneList[0].set(B.min, VectorF(-1,0,0));
polyList.mPlaneList[1].set(B.max, VectorF(0,1,0));
polyList.mPlaneList[2].set(B.max, VectorF(1,0,0));
polyList.mPlaneList[3].set(B.min, VectorF(0,-1,0));
polyList.mPlaneList[4].set(B.min, VectorF(0,0,-1));
polyList.mPlaneList[5].set(B.max, VectorF(0,0,1));
return ! gServerContainer.buildPolyList(B, mask, &polyList);
}
ConsoleFunction( initContainerRadiusSearch, void, 4, 4, "(Point3F pos, float radius, bitset mask)"
"Start a search for items within radius of pos, filtering by bitset mask.")
{
F32 x, y, z;
dSscanf(argv[1], "%g %g %g", &x, &y, &z);
F32 r = dAtof(argv[2]);
U32 mask = dAtoi(argv[3]);
gServerContainer.initRadiusSearch(Point3F(x, y, z), r, mask);
}
ConsoleFunction( containerSearchNext, S32, 1, 1, "Get next item from a search started with initContainerRadiusSearch.")
{
return gServerContainer.containerSearchNext();
}
ConsoleFunction( containerSearchCurrDist, F32, 1, 1, "Get distance of the center of the current item from the center of the current initContainerRadiusSearch.")
{
return gServerContainer.containerSearchCurrDist();
}
ConsoleFunction( containerSearchCurrRadiusDist, F32, 1, 1, "Get the distance of the closest point of the current item from the center of the current initContainerRadiusSearch.")
{
return gServerContainer.containerSearchCurrRadiusDist();
}
ConsoleFunction( containerRayCast, const char*, 4, 5, "( Point3F start, Point3F end, bitset mask, SceneObject exempt=NULL )"
"Cast a ray from start to end, checking for collision against items matching mask.\n\n"
"If exempt is specified, then it is temporarily excluded from collision checks (For "
"instance, you might want to exclude the player if said player was firing a weapon.)\n"
"@returns A string containing either null, if nothing was struck, or these fields:\n"
" - The ID of the object that was struck.\n"
" - The x, y, z position that it was struck.\n"
" - The x, y, z of the normal of the face that was struck.")
{
char *returnBuffer = Con::getReturnBuffer(256);
Point3F start, end;
dSscanf(argv[1], "%g %g %g", &start.x, &start.y, &start.z);
dSscanf(argv[2], "%g %g %g", &end.x, &end.y, &end.z);
U32 mask = dAtoi(argv[3]);
SceneObject* pExempt = NULL;
if (argc > 4) {
U32 exemptId = dAtoi(argv[4]);
Sim::findObject(exemptId, pExempt);
}
if (pExempt)
pExempt->disableCollision();
RayInfo rinfo;
S32 ret = 0;
if (gServerContainer.castRay(start, end, mask, &rinfo) == true)
ret = rinfo.object->getId();
if (pExempt)
pExempt->enableCollision();
// add the hit position and normal?
if(ret)
{
dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g",
ret, rinfo.point.x, rinfo.point.y, rinfo.point.z,
rinfo.normal.x, rinfo.normal.y, rinfo.normal.z);
}
else
{
returnBuffer[0] = '0';
returnBuffer[1] = '\0';
}
return(returnBuffer);
}
ConsoleFunctionGroupEnd( Containers );
// Utility method for bin insertion
void getBinRange(const F32 min,
const F32 max,
U32& minBin,
U32& maxBin)
{
AssertFatal(max >= min, "Error, bad range! in getBinRange");
if ((max - min) > Container::csmTotalBinSize) {
F32 minCoord = mFmod(min, Container::csmTotalBinSize);
if (minCoord < 0.0f) {
minCoord += Container::csmTotalBinSize;
// This is truly lame, but it can happen. There must be a better way to
// deal with this.
if (minCoord == Container::csmTotalBinSize)
minCoord = Container::csmTotalBinSize - 0.01;
}
AssertFatal(minCoord >= 0.0 && minCoord < Container::csmTotalBinSize, "Bad minCoord");
minBin = U32(minCoord / Container::csmBinSize);
AssertFatal(minBin < Container::csmNumBins, avar("Error, bad clipping! (%g, %d)", minCoord, minBin));
maxBin = minBin + (Container::csmNumBins - 1);
return;
} else {
F32 minCoord = mFmod(min, Container::csmTotalBinSize);
if (minCoord < 0.0f) {
minCoord += Container::csmTotalBinSize;
// This is truly lame, but it can happen. There must be a better way to
// deal with this.
if (minCoord == Container::csmTotalBinSize)
minCoord = Container::csmTotalBinSize - 0.01;
}
AssertFatal(minCoord >= 0.0 && minCoord < Container::csmTotalBinSize, "Bad minCoord");
F32 maxCoord = mFmod(max, Container::csmTotalBinSize);
if (maxCoord < 0.0f) {
maxCoord += Container::csmTotalBinSize;
// This is truly lame, but it can happen. There must be a better way to
// deal with this.
if (maxCoord == Container::csmTotalBinSize)
maxCoord = Container::csmTotalBinSize - 0.01;
}
AssertFatal(maxCoord >= 0.0 && maxCoord < Container::csmTotalBinSize, "Bad maxCoord");
minBin = U32(minCoord / Container::csmBinSize);
maxBin = U32(maxCoord / Container::csmBinSize);
AssertFatal(minBin < Container::csmNumBins, avar("Error, bad clipping(min)! (%g, %d)", maxCoord, minBin));
AssertFatal(minBin < Container::csmNumBins, avar("Error, bad clipping(max)! (%g, %d)", maxCoord, maxBin));
// MSVC6 seems to be generating some bad floating point code around
// here when full optimizations are on. The min != max test should
// not be needed, but it clears up the VC issue.
if (min != max && minCoord > maxCoord)
maxBin += Container::csmNumBins;
AssertFatal(maxBin >= minBin, "Error, min should always be less than max!");
}
}
//--------------------------------------------------------------------------
//-------------------------------------- SceneObject implementation
//
LightInfo SceneObject::LightingInfo::smAmbientLight;
SceneObject::SceneObject()
{
mContainer = 0;
mTypeMask = DefaultObjectType;
mCollisionCount = 0;
mGlobalBounds = false;
mObjScale.set(1,1,1);
mObjToWorld.identity();
mWorldToObj.identity();
mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
mWorldBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
mWorldSphere = SphereF(Point3F(0, 0, 0), 0);
mRenderObjToWorld.identity();
mRenderWorldToObj.identity();
mRenderWorldBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
mRenderWorldSphere = SphereF(Point3F(0, 0, 0), 0);
mContainerSeqKey = 0;
mBinRefHead = NULL;
mSceneManager = NULL;
mZoneRangeStart = 0xFFFFFFFF;
mNumCurrZones = 0;
mZoneRefHead = NULL;
mLastState = NULL;
mLastStateKey = 0;
mBinMinX = 0xFFFFFFFF;
mBinMaxX = 0xFFFFFFFF;
mBinMinY = 0xFFFFFFFF;
mBinMaxY = 0xFFFFFFFF;
}
SceneObject::~SceneObject()
{
AssertFatal(mZoneRangeStart == 0xFFFFFFFF && mSceneManager == NULL,
"Error, SceneObject not properly removed from sceneGraph");
AssertFatal(mZoneRefHead == NULL && mBinRefHead == NULL,
"Error, still linked in reference lists!");
unlink();
}
//----------------------------------------------------------------------------
const char* SceneObject::scriptThis()
{
return Con::getIntArg(getId());
}
//--------------------------------------------------------------------------
void SceneObject::buildConvex(const Box3F&, Convex*)
{
return;
}
bool SceneObject::buildPolyList(AbstractPolyList*, const Box3F&, const SphereF&)
{
return false;
}
BSPNode *SceneObject::buildCollisionBSP(BSPTree*, const Box3F&, const SphereF&)
{
return NULL;
}
bool SceneObject::castRay(const Point3F&, const Point3F&, RayInfo*)
{
return false;
}
bool SceneObject::collideBox(const Point3F &start, const Point3F &end, RayInfo *info)
{
const F32 * pStart = (const F32*)start;
const F32 * pEnd = (const F32*)end;
const F32 * pMin = (const F32*)mObjBox.min;
const F32 * pMax = (const F32*)mObjBox.max;
F32 maxStartTime = -1;
F32 minEndTime = 1;
F32 startTime;
F32 endTime;
// used for getting normal
U32 hitIndex;
U32 side;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -