📄 shapebase.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "dgl/dgl.h"
#include "platform/platform.h"
#include "core/dnet.h"
#include "audio/audioDataBlock.h"
#include "game/gameConnection.h"
#include "game/moveManager.h"
#include "console/consoleTypes.h"
#include "core/bitStream.h"
#include "ts/tsPartInstance.h"
#include "ts/tsShapeInstance.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "game/shadow.h"
#include "game/fx/explosion.h"
#include "game/shapeBase.h"
#include "terrain/waterBlock.h"
#include "game/debris.h"
#include "terrain/sky.h"
#include "game/physicalZone.h"
#include "sceneGraph/detailManager.h"
#include "math/mathUtils.h"
#include "math/mMatrix.h"
#include "math/mRandom.h"
#include "platform/profiler.h"
IMPLEMENT_CO_DATABLOCK_V1(ShapeBaseData);
#ifdef TGE_RPG
//leo 2006.5.12
//Camera与主角距离
static F32 ms_fCameraYaw = 0;
static F32 ms_fCameraPitch = 0;//M_PI/4;
static F32 ms_fCameraDist = 0;
static F32 ms_fCameraMinPitch = 5;
static F32 ms_fCameraMaxPitch = 89.9; //不可为90,相机会倒过来的
#endif
//----------------------------------------------------------------------------
// Timeout for non-looping sounds on a channel
static SimTime sAudioTimeout = 500;
bool ShapeBase::gRenderEnvMaps = true;
F32 ShapeBase::sWhiteoutDec = 0.007;
F32 ShapeBase::sDamageFlashDec = 0.007;
U32 ShapeBase::sLastRenderFrame = 0;
static const char *sDamageStateName[] =
{
// Index by enum ShapeBase::DamageState
"Enabled",
"Disabled",
"Destroyed"
};
//----------------------------------------------------------------------------
ShapeBaseData::ShapeBaseData()
{
shapeName = "";
cloakTexName = "";
mass = 1;
drag = 0;
density = 1;
maxEnergy = 0;
maxDamage = 1.0;
disabledLevel = 1.0;
destroyedLevel = 1.0;
repairRate = 0.0033;
eyeNode = -1;
shadowNode = -1;
cameraNode = -1;
damageSequence = -1;
hulkSequence = -1;
#ifdef TGE_RPG /// TGE_Move
cameraDefaultDist = 6.f;
cameraMaxDist = 20.f;
cameraMinDist = 3.f;
cameraDefaultYaw = 0.f;
cameraDefaultPitch= 35.f;
#else
cameraMaxDist = 0;
cameraMinDist = 0.2;
#endif
cameraDefaultFov = 90.f;
cameraMinFov = 5.f;
cameraMaxFov = 120.f;
emap = false;
aiAvoidThis = false;
isInvincible = false;
renderWhenDestroyed = true;
debris = NULL;
debrisID = 0;
debrisShapeName = NULL;
explosion = NULL;
explosionID = 0;
underwaterExplosion = NULL;
underwaterExplosionID = 0;
firstPersonOnly = false;
useEyePoint = false;
observeThroughObject = false;
computeCRC = false;
// no shadows by default
genericShadowLevel = 2.0f;
noShadowLevel = 2.0f;
inheritEnergyFromMount = false;
for(U32 j = 0; j < NumHudRenderImages; j++)
{
hudImageNameFriendly[j] = 0;
hudImageNameEnemy[j] = 0;
hudRenderCenter[j] = false;
hudRenderModulated[j] = false;
hudRenderAlways[j] = false;
hudRenderDistance[j] = false;
hudRenderName[j] = false;
}
#ifdef TGE_RPGCLIENT2//TGE_RPGClient2
mCRC = 1;
#endif
}
static ShapeBaseData gShapeBaseDataProto;
ShapeBaseData::~ShapeBaseData()
{
}
bool ShapeBaseData::preload(bool server, char errorBuffer[256])
{
if (!Parent::preload(server, errorBuffer))
return false;
#ifdef TGE_RPG
if(server)
return true;
#endif
bool shapeError = false;
// Resolve objects transmitted from server
if (!server) {
if( !explosion && explosionID != 0 )
{
if( Sim::findObject( explosionID, explosion ) == false)
{
Con::errorf( ConsoleLogEntry::General, "ShapeBaseData::preload: Invalid packet, bad datablockId(explosion): 0x%x", explosionID );
}
AssertFatal(!(explosion && ((explosionID < DataBlockObjectIdFirst) || (explosionID > DataBlockObjectIdLast))),
"ShapeBaseData::preload: invalid explosion data");
}
if( !underwaterExplosion && underwaterExplosionID != 0 )
{
if( Sim::findObject( underwaterExplosionID, underwaterExplosion ) == false)
{
Con::errorf( ConsoleLogEntry::General, "ShapeBaseData::preload: Invalid packet, bad datablockId(underwaterExplosion): 0x%x", underwaterExplosionID );
}
AssertFatal(!(underwaterExplosion && ((underwaterExplosionID < DataBlockObjectIdFirst) || (underwaterExplosionID > DataBlockObjectIdLast))),
"ShapeBaseData::preload: invalid underwaterExplosion data");
}
if( !debris && debrisID != 0 )
{
Sim::findObject( debrisID, debris );
AssertFatal(!(debris && ((debrisID < DataBlockObjectIdFirst) || (debrisID > DataBlockObjectIdLast))),
"ShapeBaseData::preload: invalid debris data");
}
if( debrisShapeName && debrisShapeName[0] != '\0' && !bool(debrisShape) )
{
debrisShape = ResourceManager->load(debrisShapeName);
if( bool(debrisShape) == false )
{
dSprintf(errorBuffer, 256, "ShapeBaseData::load: Couldn't load shape \"%s\"", debrisShapeName);
return false;
}
else
{
if(!server && !debrisShape->preloadMaterialList() && NetConnection::filesWereDownloaded())
shapeError = true;
TSShapeInstance* pDummy = new TSShapeInstance(debrisShape, !server);
delete pDummy;
}
}
}
//
if (shapeName && shapeName[0]) {
S32 i;
// Resolve shapename
shape = ResourceManager->load(shapeName, computeCRC);
if (!bool(shape)) {
dSprintf(errorBuffer, 256, "ShapeBaseData: Couldn't load shape \"%s\"",shapeName);
return false;
}
if(!server && !shape->preloadMaterialList() && NetConnection::filesWereDownloaded())
shapeError = true;
if(computeCRC)
{
#ifdef TGE_RPGCLIENT2 // TGE_RPGClientPreload
mCRC = shape.getCRC();
#else
Con::printf("Validation required for shape: %s", shapeName);
if(server)
mCRC = shape.getCRC();
else if(mCRC != shape.getCRC())
{
dSprintf(errorBuffer, 256, "Shape \"%s\" does not match version on server.",shapeName);
return false;
}
#endif
}
// Resolve details and camera node indexes.
for (i = 0; i < shape->details.size(); i++)
{
char* name = (char*)shape->names[shape->details[i].nameIndex];
if (dStrstr((const char *)dStrlwr(name), "collision-"))
{
collisionDetails.push_back(i);
collisionBounds.increment();
shape->computeBounds(collisionDetails.last(), collisionBounds.last());
shape->getAccelerator(collisionDetails.last());
if (!shape->bounds.isContained(collisionBounds.last()))
{
Con::warnf("Warning: shape %s collision detail %d (Collision-%d) bounds exceed that of shape.", shapeName, collisionDetails.size() - 1, collisionDetails.last());
collisionBounds.last() = shape->bounds;
}
else if (collisionBounds.last().isValidBox() == false)
{
Con::errorf("Error: shape %s-collision detail %d (Collision-%d) bounds box invalid!", shapeName, collisionDetails.size() - 1, collisionDetails.last());
collisionBounds.last() = shape->bounds;
}
// The way LOS works is that it will check to see if there is a LOS detail that matches
// the the collision detail + 1 + MaxCollisionShapes (this variable name should change in
// the future). If it can't find a matching LOS it will simply use the collision instead.
// We check for any "unmatched" LOS's further down
LOSDetails.increment();
char buff[128];
dSprintf(buff, sizeof(buff), "LOS-%d", i + 1 + MaxCollisionShapes);
U32 los = shape->findDetail(buff);
if (los == -1)
LOSDetails.last() = i;
else
LOSDetails.last() = los;
}
}
// Snag any "unmatched" LOS details
for (i = 0; i < shape->details.size(); i++)
{
char* name = (char*)shape->names[shape->details[i].nameIndex];
if (dStrstr((const char *)dStrlwr(name), "los-"))
{
// See if we already have this LOS
bool found = false;
for (U32 j = 0; j < LOSDetails.size(); j++)
{
if (LOSDetails[j] == i)
{
found = true;
break;
}
}
if (!found)
LOSDetails.push_back(i);
}
}
debrisDetail = shape->findDetail("Debris-17");
eyeNode = shape->findNode("eye");
cameraNode = shape->findNode("cam");
if (cameraNode == -1)
cameraNode = eyeNode;
// Resolve mount point node indexes
for (i = 0; i < NumMountPoints; i++) {
char fullName[256];
dSprintf(fullName,sizeof(fullName),"mount%d",i);
mountPointNode[i] = shape->findNode(fullName);
}
// find the AIRepairNode - hardcoded to be the last node in the array...
mountPointNode[AIRepairNode] = shape->findNode("AIRepairNode");
//
hulkSequence = shape->findSequence("Visibility");
damageSequence = shape->findSequence("Damage");
//
#ifdef TGE_RPG /// TGE_Move
cameraDefaultDist = mClamp(cameraDefaultDist, cameraMinDist, cameraMaxDist);
cameraDefaultPitch = mClampF(cameraDefaultPitch, ms_fCameraMinPitch, ms_fCameraMaxPitch);
cameraDefaultYaw = mFmod(cameraDefaultYaw, 360.f);
#else
F32 w = shape->bounds.len_y() / 2;
if (cameraMaxDist < w)
cameraMaxDist = w;
#endif
}
if(!server)
{
// grab all the hud images
for(U32 i = 0; i < NumHudRenderImages; i++)
{
if(hudImageNameFriendly[i] && hudImageNameFriendly[i][0])
hudImageFriendly[i] = TextureHandle(hudImageNameFriendly[i], BitmapTexture);
if(hudImageNameEnemy[i] && hudImageNameEnemy[i][0])
hudImageEnemy[i] = TextureHandle(hudImageNameEnemy[i], BitmapTexture);
}
}
return !shapeError;
}
void ShapeBaseData::initPersistFields()
{
Parent::initPersistFields();
addGroup("Render");
addField("shapeFile", TypeFilename, Offset(shapeName, ShapeBaseData));
addField("cloakTexture", TypeFilename, Offset(cloakTexName, ShapeBaseData));
addField("emap", TypeBool, Offset(emap, ShapeBaseData));
endGroup("Render");
addGroup("Destruction", "Parameters related to the destruction effects of this object.");
addField("explosion", TypeExplosionDataPtr, Offset(explosion, ShapeBaseData));
addField("underwaterExplosion", TypeExplosionDataPtr, Offset(underwaterExplosion, ShapeBaseData));
addField("debris", TypeDebrisDataPtr, Offset(debris, ShapeBaseData));
addField("renderWhenDestroyed", TypeBool, Offset(renderWhenDestroyed, ShapeBaseData));
addField("debrisShapeName", TypeFilename, Offset(debrisShapeName, ShapeBaseData));
endGroup("Destruction");
addGroup("Physics");
addField("mass", TypeF32, Offset(mass, ShapeBaseData));
addField("drag", TypeF32, Offset(drag, ShapeBaseData));
addField("density", TypeF32, Offset(density, ShapeBaseData));
endGroup("Physics");
addGroup("Damage/Energy");
addField("maxEnergy", TypeF32, Offset(maxEnergy, ShapeBaseData));
addField("maxDamage", TypeF32, Offset(maxDamage, ShapeBaseData));
addField("disabledLevel", TypeF32, Offset(disabledLevel, ShapeBaseData));
addField("destroyedLevel", TypeF32, Offset(destroyedLevel, ShapeBaseData));
addField("repairRate", TypeF32, Offset(repairRate, ShapeBaseData));
addField("inheritEnergyFromMount", TypeBool, Offset(inheritEnergyFromMount, ShapeBaseData));
addField("isInvincible", TypeBool, Offset(isInvincible, ShapeBaseData));
endGroup("Damage/Energy");
addGroup("Camera");
#ifdef TGE_RPG /// TGE_Move
addField("cameraDefaultDist", TypeF32, Offset(cameraDefaultDist, ShapeBaseData));
#endif
addField("cameraMaxDist", TypeF32, Offset(cameraMaxDist, ShapeBaseData));
addField("cameraMinDist", TypeF32, Offset(cameraMinDist, ShapeBaseData));
#ifdef TGE_RPG /// TGE_Move
addField("cameraDefaultPitch", TypeF32, Offset(cameraDefaultPitch, ShapeBaseData));
addField("cameraDefaultYaw", TypeF32, Offset(cameraDefaultYaw, ShapeBaseData));
#endif
addField("cameraDefaultFov", TypeF32, Offset(cameraDefaultFov, ShapeBaseData));
addField("cameraMinFov", TypeF32, Offset(cameraMinFov, ShapeBaseData));
addField("cameraMaxFov", TypeF32, Offset(cameraMaxFov, ShapeBaseData));
addField("firstPersonOnly", TypeBool, Offset(firstPersonOnly, ShapeBaseData));
addField("useEyePoint", TypeBool, Offset(useEyePoint, ShapeBaseData));
addField("observeThroughObject", TypeBool, Offset(observeThroughObject, ShapeBaseData));
endGroup("Camera");
// This hud code is going to get ripped out soon...
addGroup("HUD", "@deprecated Likely to be removed soon.");
addField("hudImageName", TypeFilename, Offset(hudImageNameFriendly, ShapeBaseData), NumHudRenderImages);
addField("hudImageNameFriendly", TypeFilename, Offset(hudImageNameFriendly, ShapeBaseData), NumHudRenderImages);
addField("hudImageNameEnemy", TypeFilename, Offset(hudImageNameEnemy, ShapeBaseData), NumHudRenderImages);
addField("hudRenderCenter", TypeBool, Offset(hudRenderCenter, ShapeBaseData), NumHudRenderImages);
addField("hudRenderModulated", TypeBool, Offset(hudRenderModulated, ShapeBaseData), NumHudRenderImages);
addField("hudRenderAlways", TypeBool, Offset(hudRenderAlways, ShapeBaseData), NumHudRenderImages);
addField("hudRenderDistance", TypeBool, Offset(hudRenderDistance, ShapeBaseData), NumHudRenderImages);
addField("hudRenderName", TypeBool, Offset(hudRenderName, ShapeBaseData), NumHudRenderImages);
endGroup("HUD");
addGroup("Misc");
addField("aiAvoidThis", TypeBool, Offset(aiAvoidThis, ShapeBaseData));
addField("computeCRC", TypeBool, Offset(computeCRC, ShapeBaseData));
endGroup("Misc");
}
ConsoleMethod( ShapeBaseData, checkDeployPos, bool, 3, 3, "(Transform xform)")
{
if (bool(object->shape) == false)
return false;
Point3F pos(0, 0, 0);
AngAxisF aa(Point3F(0, 0, 1), 0);
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);
Box3F objBox = object->shape->bounds;
Point3F boxCenter = (objBox.min + objBox.max) * 0.5;
objBox.min = boxCenter + (objBox.min - boxCenter) * 0.9;
objBox.max = boxCenter + (objBox.max - boxCenter) * 0.9;
Box3F wBox = objBox;
mat.mul(wBox);
EarlyOutPolyList polyList;
polyList.mNormal.set(0,0,0);
polyList.mPlaneList.clear();
polyList.mPlaneList.setSize(6);
polyList.mPlaneList[0].set(objBox.min,VectorF(-1,0,0));
polyList.mPlaneList[1].set(objBox.max,VectorF(0,1,0));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -