Merge branch 'development' of https://github.com/GarageGames/Torque3D into FrameMallocMallet

Conflicts:
	Engine/source/gfx/gl/gfxGLTextureManager.cpp
This commit is contained in:
Azaezel 2016-06-06 01:20:23 -05:00
commit 75fa06dec2
91 changed files with 2132 additions and 483 deletions

View file

@ -190,13 +190,15 @@ void LightAnimData::AnimValue<COUNT>::updateKey()
}
template<U32 COUNT>
bool LightAnimData::AnimValue<COUNT>::animate( F32 time, F32 *output )
bool LightAnimData::AnimValue<COUNT>::animate(F32 time, F32 *output, bool multiply)
{
F32 scaledTime, lerpFactor, valueRange, keyFrameLerp;
U32 posFrom, posTo;
S32 keyFrameFrom, keyFrameTo;
F32 initialValue = *output;
if (!multiply)
initialValue = 1;
bool wasAnimated = false;
for ( U32 i=0; i < COUNT; i++ )
@ -305,6 +307,6 @@ void LightAnimData::animate( LightInfo *lightInfo, LightAnimState *state )
lightInfo->setColor( color );
F32 brightness = state->brightness;
mBrightness.animate( time, &brightness );
mBrightness.animate( time, &brightness, true );
lightInfo->setBrightness( brightness );
}

View file

@ -151,7 +151,7 @@ public:
/// Performs the animation returning the results in the output if
/// the time scale is greater than zero.
/// @return Returns true if the animation was performed.
bool animate( F32 time, F32 *output );
bool animate(F32 time, F32 *output, bool multiply = false);
/// Called when the key string is changed to update the
/// key length and time scale.

View file

@ -378,3 +378,25 @@ void BtBody::setSimulationEnabled( bool enabled )
mIsEnabled = enabled;
}
void BtBody::moveKinematicTo(const MatrixF &transform)
{
AssertFatal(mActor, "BtBody::moveKinematicTo - The actor is null!");
U32 bodyflags = mActor->getCollisionFlags();
const bool isKinematic = bodyflags & BF_KINEMATIC;
if (!isKinematic)
{
Con::errorf("BtBody::moveKinematicTo is only for kinematic bodies.");
return;
}
if (mCenterOfMass)
{
MatrixF xfm;
xfm.mul(transform, *mCenterOfMass);
mActor->setCenterOfMassTransform(btCast<btTransform>(xfm));
}
else
mActor->setCenterOfMassTransform(btCast<btTransform>(transform));
}

View file

@ -111,6 +111,8 @@ public:
F32 staticFriction );
virtual void applyCorrection( const MatrixF &xfm );
virtual void applyImpulse( const Point3F &origin, const Point3F &force );
virtual void moveKinematicTo(const MatrixF &xfm);
};
#endif // _T3D_PHYSICS_BTBODY_H_

View file

@ -71,6 +71,7 @@ void BtPlayer::init( const char *type,
mObject = obj;
mWorld = (BtWorld*)world;
mSlopeAngle = runSurfaceCos;
mStepHeight = stepHeight;
//if ( dStricmp( type, "Capsule" ) == 0 )
@ -102,6 +103,17 @@ Point3F BtPlayer::move( const VectorF &disp, CollisionList &outCol )
{
AssertFatal( mGhostObject, "BtPlayer::move - The controller is null!" );
if (!mWorld->isEnabled())
{
btTransform currentTrans = mGhostObject->getWorldTransform();
btVector3 currentPos = currentTrans.getOrigin();
Point3F returnPos = btCast<Point3F>(currentPos);
returnPos.z -= mOriginOffset;
return returnPos;
}
// First recover from any penetrations from the previous tick.
U32 numPenetrationLoops = 0;
bool touchingContact = false;
@ -305,16 +317,9 @@ bool BtPlayer::_sweep( btVector3 *inOutCurrPos, const btVector3 &disp, Collision
col.normal = btCast<Point3F>( callback.m_hitNormalWorld );
col.object = PhysicsUserData::getObject( callback.m_hitCollisionObject->getUserPointer() );
if (disp.z() < 0.0f)
{
// We're sweeping down as part of the stepping routine. In this
// case we want to have the collision normal only point in the opposite direction.
// i.e. up If we include the sideways part of the normal then the Player class
// velocity calculations using this normal will affect the player's forwards
// momentum. This is especially noticable on stairs as the rounded bottom of
// the capsule slides up the corner of a stair.
col.normal.set(0.0f, 0.0f, 1.0f);
}
F32 vd = col.normal.z;
if (vd < mSlopeAngle)
return false;
}
return true;

View file

@ -57,6 +57,10 @@ protected:
///
F32 mOriginOffset;
///
F32 mSlopeAngle;
///
///
F32 mStepHeight;
///

View file

@ -113,6 +113,10 @@ public:
///
virtual void applyImpulse( const Point3F &origin, const Point3F &force ) = 0;
///
virtual void moveKinematicTo(const MatrixF &xfm) = 0;
};

View file

@ -417,3 +417,22 @@ void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force )
}
void Px3Body::moveKinematicTo(const MatrixF &transform)
{
AssertFatal(mActor, "Px3Body::moveKinematicTo - The actor is null!");
const bool isKinematic = mBodyFlags & BF_KINEMATIC;
if (!isKinematic)
{
Con::errorf("Px3Body::moveKinematicTo is only for kinematic bodies.");
return;
}
mWorld->lockScene();
physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
actor->setKinematicTarget(px3Cast<physx::PxTransform>(transform));
mWorld->unlockScene();
}

View file

@ -117,6 +117,8 @@ public:
F32 staticFriction );
virtual void applyCorrection( const MatrixF &xfm );
virtual void applyImpulse( const Point3F &origin, const Point3F &force );
virtual void moveKinematicTo(const MatrixF &xfm);
};
#endif // _PX3BODY_H_

View file

@ -329,3 +329,33 @@ Box3F Px3Player::getWorldBounds()
return px3Cast<Box3F>( bounds );
}
bool Px3Player::testSpacials(const Point3F &nPos, const Point3F &nSize) const
{
F32 offset = nSize.z * 0.5f;
F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth;
F32 height = (nSize.z - (radius * 2.0f)) * 0.5f;
height -= mSkinWidth * 2.0f;
physx::PxCapsuleGeometry geom(radius, height);
physx::PxVec3 pos(nPos.x, nPos.y, nPos.z + offset);
physx::PxQuat orientation(Float_HalfPi, physx::PxVec3(0.0f, 1.0f, 0.0f));
physx::PxOverlapBuffer hit;
physx::PxQueryFilterData queryFilter(physx::PxQueryFlag::eANY_HIT | physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC);
queryFilter.data.word0 = PX3_DEFAULT;
bool hasHit = mWorld->getScene()->overlap(geom, physx::PxTransform(pos, orientation), hit, queryFilter);
return !hasHit; // Return true if there are no overlapping objects
}
void Px3Player::setSpacials(const Point3F &nPos, const Point3F &nSize)
{
mOriginOffset = nSize.z * 0.5f;
F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth;
F32 height = nSize.z - (radius * 2.0f);
height -= mSkinWidth * 2.0f;
mWorld->releaseWriteLock();
mController->resize(height);
px3GetFirstShape(mController->getActor())->getCapsuleGeometry(mGeometry);
}

View file

@ -94,8 +94,8 @@ public:
PhysicsWorld *world );
virtual Point3F move( const VectorF &displacement, CollisionList &outCol );
virtual void findContact( SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects ) const;
virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const { return true; }
virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ) {}
virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const;
virtual void setSpacials( const Point3F &nPos, const Point3F &nSize );
virtual void enableCollision();
virtual void disableCollision();
};

View file

@ -62,7 +62,8 @@ Px3World::Px3World(): mScene( NULL ),
mIsEnabled( false ),
mEditorTimeScale( 1.0f ),
mAccumulator( 0 ),
mControllerManager( NULL )
mControllerManager(NULL),
mIsSceneLocked(false)
{
}
@ -335,6 +336,62 @@ void Px3World::releaseWriteLock()
//AssertFatal( mScene->isWritable(), "PhysX3World::releaseWriteLock() - We should have been writable now!" );
}
void Px3World::lockScenes()
{
Px3World *world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("server"));
if (world)
world->lockScene();
world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("client"));
if (world)
world->lockScene();
}
void Px3World::unlockScenes()
{
Px3World *world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("server"));
if (world)
world->unlockScene();
world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("client"));
if (world)
world->unlockScene();
}
void Px3World::lockScene()
{
if (!mScene)
return;
if (mIsSceneLocked)
{
Con::printf("Px3World: Attempting to lock a scene that is already locked.");
return;
}
mScene->lockWrite();
mIsSceneLocked = true;
}
void Px3World::unlockScene()
{
if (!mScene)
return;
if (!mIsSceneLocked)
{
Con::printf("Px3World: Attempting to unlock a scene that is not locked.");
return;
}
mScene->unlockWrite();
mIsSceneLocked = false;
}
bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse )
{

View file

@ -56,6 +56,7 @@ protected:
bool mIsEnabled;
bool mIsSimulating;
bool mIsServer;
bool mIsSceneLocked;
U32 mTickCount;
ProcessList *mProcessList;
F32 mEditorTimeScale;
@ -96,11 +97,15 @@ public:
void releaseWriteLock();
bool isServer(){return mIsServer;}
physx::PxController* createController( physx::PxControllerDesc &desc );
void lockScene();
void unlockScene();
//static
static bool restartSDK( bool destroyOnly = false, Px3World *clientWorld = NULL, Px3World *serverWorld = NULL );
static void releaseWriteLocks();
static physx::PxCooking *getCooking();
static void setTiming(F32 stepTime,U32 maxIterations);
static void lockScenes();
static void unlockScenes();
};
#endif // _PX3WORLD_H_

View file

@ -4881,17 +4881,18 @@ DefineEngineMethod( ShapeBase, getTargetCount, S32, (),,
"@see getTargetName()\n")
{
ShapeBase *obj = dynamic_cast< ShapeBase* > ( object );
if(obj)
{
// Try to use the client object (so we get the reskinned targets in the Material Editor)
if ((ShapeBase*)obj->getClientObject())
obj = (ShapeBase*)obj->getClientObject();
ShapeBase *obj = dynamic_cast< ShapeBase* > ( object );
if(obj)
{
// Try to use the client object (so we get the reskinned targets in the Material Editor)
if ((ShapeBase*)obj->getClientObject())
obj = (ShapeBase*)obj->getClientObject();
return obj->getShapeInstance()->getTargetCount();
if (obj->getShapeInstance() != NULL)
return obj->getShapeInstance()->getTargetCount();
}
return -1;
return -1;
}
DefineEngineMethod( ShapeBase, changeMaterial, void, ( const char* mapTo, Material* oldMat, Material* newMat ),,

View file

@ -46,6 +46,9 @@
#include "gfx/primBuilder.h"
#include "gfx/gfxDrawUtil.h"
#include "materials/materialDefinition.h"
#include "T3D/physics/physicsPlugin.h"
#include "T3D/physics/physicsBody.h"
#include "T3D/physics/physicsCollision.h"
namespace {
@ -203,7 +206,8 @@ VehicleData::VehicleData()
dMemset(waterSound, 0, sizeof(waterSound));
collDamageThresholdVel = 20;
collDamageMultiplier = 0.05f;
collDamageMultiplier = 0.05f;
enablePhysicsRep = true;
}
@ -315,6 +319,7 @@ void VehicleData::packData(BitStream* stream)
stream->write(softSplashSoundVel);
stream->write(medSplashSoundVel);
stream->write(hardSplashSoundVel);
stream->write(enablePhysicsRep);
// write the water sound profiles
for(i = 0; i < MaxSounds; i++)
@ -411,6 +416,7 @@ void VehicleData::unpackData(BitStream* stream)
stream->read(&softSplashSoundVel);
stream->read(&medSplashSoundVel);
stream->read(&hardSplashSoundVel);
stream->read(&enablePhysicsRep);
// write the water sound profiles
for(i = 0; i < MaxSounds; i++)
@ -465,6 +471,11 @@ void VehicleData::unpackData(BitStream* stream)
void VehicleData::initPersistFields()
{
addGroup("Physics");
addField("enablePhysicsRep", TypeBool, Offset(enablePhysicsRep, VehicleData),
"@brief Creates a representation of the object in the physics plugin.\n");
endGroup("Physics");
addField( "jetForce", TypeF32, Offset(jetForce, VehicleData),
"@brief Additional force applied to the vehicle when it is jetting.\n\n"
"For WheeledVehicles, the force is applied in the forward direction. For "
@ -682,6 +693,8 @@ Vehicle::Vehicle()
mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
mPhysicsRep = NULL;
}
U32 Vehicle::getCollisionMask()
@ -695,6 +708,25 @@ Point3F Vehicle::getVelocity() const
return mRigid.linVelocity;
}
void Vehicle::_createPhysics()
{
SAFE_DELETE(mPhysicsRep);
if (!PHYSICSMGR || !mDataBlock->enablePhysicsRep)
return;
TSShape *shape = mShapeInstance->getShape();
PhysicsCollision *colShape = NULL;
colShape = shape->buildColShape(false, getScale());
if (colShape)
{
PhysicsWorld *world = PHYSICSMGR->getWorld(isServerObject() ? "server" : "client");
mPhysicsRep = PHYSICSMGR->createBody();
mPhysicsRep->init(colShape, 0, PhysicsBody::BF_KINEMATIC, this, world);
mPhysicsRep->setTransform(getTransform());
}
}
//----------------------------------------------------------------------------
bool Vehicle::onAdd()
@ -776,11 +808,15 @@ bool Vehicle::onAdd()
mConvex.box.maxExtents.convolve(mObjScale);
mConvex.findNodeTransform();
_createPhysics();
return true;
}
void Vehicle::onRemove()
{
SAFE_DELETE(mPhysicsRep);
U32 i=0;
for( i=0; i<VehicleData::VC_NUM_DUST_EMITTERS; i++ )
{
@ -880,6 +916,11 @@ void Vehicle::processTick(const Move* move)
setPosition(mRigid.linPosition, mRigid.angPosition);
setMaskBits(PositionMask);
updateContainer();
//TODO: Only update when position has actually changed
//no need to check if mDataBlock->enablePhysicsRep is false as mPhysicsRep will be NULL if it is
if (mPhysicsRep)
mPhysicsRep->moveKinematicTo(getTransform());
}
}

View file

@ -127,6 +127,8 @@ struct VehicleData: public ShapeBaseData
F32 splashFreqMod;
F32 splashVelEpsilon;
bool enablePhysicsRep;
//
VehicleData();
bool preload(bool server, String &errorStr);
@ -142,6 +144,7 @@ struct VehicleData: public ShapeBaseData
//----------------------------------------------------------------------------
class PhysicsBody;
class Vehicle: public ShapeBase
{
@ -177,6 +180,8 @@ class Vehicle: public ShapeBase
Point3F cameraRotVec;
};
PhysicsBody *mPhysicsRep;
StateDelta mDelta;
S32 mPredictionCount; ///< Number of ticks to predict
VehicleData* mDataBlock;
@ -262,6 +267,8 @@ public:
bool onAdd();
void onRemove();
void _createPhysics();
/// Interpolates between move ticks @see processTick
/// @param dt Change in time between the last call and this call to the function
void interpolateTick(F32 dt);

View file

@ -74,6 +74,8 @@ DefineConsoleType( TypeCommand, String )
DefineConsoleType( TypeFilename, const char * )
DefineConsoleType( TypeStringFilename, String )
DefineConsoleType(TypeRotationF, RotationF)
/// A universally unique identifier.
DefineConsoleType( TypeUUID, Torque::UUID )

View file

@ -1015,7 +1015,7 @@ void GFXDrawUtil::_drawSolidPolyhedron( const GFXStateBlockDesc &desc, const Any
// Allocate a temp buffer for the face indices.
const U32 numIndices = poly.getNumEdges() * 2;
const U32 numIndices = poly.getNumEdges() * 3;
const U32 numPlanes = poly.getNumPlanes();
GFXPrimitiveBufferHandle prims( mDevice, numIndices, 0, GFXBufferTypeVolatile );

View file

@ -56,54 +56,32 @@ void GFXGLCardProfiler::setupCardCapabilities()
{
GLint maxTexSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
const char* versionString = reinterpret_cast<const char*>(glGetString(GL_VERSION));
F32 glVersion = dAtof(versionString);
// OpenGL doesn't have separate maximum width/height.
setCapability("maxTextureWidth", maxTexSize);
setCapability("maxTextureHeight", maxTexSize);
setCapability("maxTextureSize", maxTexSize);
// If extensions haven't been inited, we're in trouble here.
bool suppVBO = (gglHasExtension(ARB_vertex_buffer_object) || glVersion >= 1.499f);
setCapability("GL::suppVertexBufferObject", suppVBO);
// check if render to texture supported is available
bool suppRTT = gglHasExtension(EXT_framebuffer_object);
setCapability("GL::suppRenderTexture", suppRTT);
bool suppBlit = gglHasExtension(EXT_framebuffer_blit);
setCapability("GL::suppRTBlit", suppBlit);
bool suppFloatTex = gglHasExtension(ARB_texture_float);
setCapability("GL::suppFloatTexture", suppFloatTex);
// Check for anisotropic filtering support.
bool suppAnisotropic = gglHasExtension( EXT_texture_filter_anisotropic );
setCapability( "GL::suppAnisotropic", suppAnisotropic );
setCapability("GL_EXT_texture_filter_anisotropic", gglHasExtension(EXT_texture_filter_anisotropic));
// check to see if we have the fragment shader extension or the gl version is high enough for glsl to be core
// also check to see if the language version is high enough
F32 glslVersion = dAtof(reinterpret_cast<const char*>(glGetString( GL_SHADING_LANGUAGE_VERSION)));
bool suppSPU = (gglHasExtension(ARB_fragment_shader) || glVersion >= 1.999f) && glslVersion >= 1.0999;
setCapability("GL::suppFragmentShader", suppSPU);
bool suppAppleFence = gglHasExtension(APPLE_fence);
setCapability("GL::APPLE::suppFence", suppAppleFence);
// When enabled, call glGenerateMipmapEXT() to generate mipmaps instead of relying on GL_GENERATE_MIPMAP
setCapability("GL::Workaround::needsExplicitGenerateMipmap", false);
// When enabled, binds and unbinds a texture target before doing the depth buffer copy. Failure to do
// so will cause a hard freeze on Mac OS 10.4 with a Radeon X1600
setCapability("GL::Workaround::X1600DepthBufferCopy", false);
// When enabled, does not copy the last column and row of the depth buffer in a depth buffer copy. Failure
// to do so will cause a kernel panic on Mac OS 10.5(.1) with a Radeon HD 2600 (fixed in 10.5.2)
setCapability("GL::Workaround::HD2600DepthBufferCopy", false);
// Certain Intel drivers have a divide by 0 crash if mipmaps are specified with
// glTexSubImage2D.
setCapability("GL::Workaround::noManualMips", false);
// Check for buffer storage
setCapability("GL_ARB_buffer_storage", gglHasExtension(ARB_buffer_storage));
// Check for shader model 5.0
setCapability("GL_ARB_gpu_shader5", gglHasExtension(ARB_gpu_shader5));
// Check for texture storage
setCapability("GL_ARB_texture_storage", gglHasExtension(ARB_texture_storage));
// Check for sampler objects
setCapability("GL_ARB_sampler_objects", gglHasExtension(ARB_sampler_objects));
// Check for copy image support
setCapability("GL_ARB_copy_image", gglHasExtension(ARB_copy_image));
// Check for vertex attrib binding
setCapability("GL_ARB_vertex_attrib_binding", gglHasExtension(ARB_vertex_attrib_binding));
}
bool GFXGLCardProfiler::_queryCardCap(const String& query, U32& foundResult)

View file

@ -20,7 +20,8 @@ public:
}
void init(U32 start, U32 end)
{
{
PROFILE_SCOPE(GFXGLQueryFence_issue);
mStart = start;
mEnd = end;
mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
@ -35,7 +36,8 @@ public:
}
void wait()
{
{
PROFILE_SCOPE(GFXGLQueryFence_block);
GLbitfield waitFlags = 0;
GLuint64 waitDuration = 0;
while( 1 )
@ -158,7 +160,7 @@ public:
const U32 cSizeInMB = 10;
mBufferSize = (cSizeInMB << 20);
if( gglHasExtension(ARB_buffer_storage) )
if( GFXGL->mCapabilities.bufferStorage )
{
const GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
glBufferStorage(mBinding, mBufferSize, NULL, flags);
@ -198,7 +200,7 @@ public:
outOffset = mBufferFreePos;
if( gglHasExtension(ARB_buffer_storage) )
if( GFXGL->mCapabilities.bufferStorage )
{
outPtr = (U8*)(mBufferPtr) + mBufferFreePos;
}
@ -227,7 +229,7 @@ public:
void unlock()
{
if( gglHasExtension(ARB_buffer_storage) )
if( GFXGL->mCapabilities.bufferStorage )
{
return;
}

View file

@ -140,10 +140,18 @@ void GFXGLDevice::initGLState()
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// [JTH 5/6/2016] GLSL 1.50 is really SM 4.0
// Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run.
mPixelShaderVersion = 3.0;
mSupportsAnisotropic = mCardProfiler->queryProfile( "GL::suppAnisotropic" );
// Set capability extensions.
mCapabilities.anisotropicFiltering = mCardProfiler->queryProfile("GL_EXT_texture_filter_anisotropic");
mCapabilities.bufferStorage = mCardProfiler->queryProfile("GL_ARB_buffer_storage");
mCapabilities.shaderModel5 = mCardProfiler->queryProfile("GL_ARB_gpu_shader5");
mCapabilities.textureStorage = mCardProfiler->queryProfile("GL_ARB_texture_storage");
mCapabilities.samplerObjects = mCardProfiler->queryProfile("GL_ARB_sampler_objects");
mCapabilities.copyImage = mCardProfiler->queryProfile("GL_ARB_copy_image");
mCapabilities.vertexAttributeBinding = mCardProfiler->queryProfile("GL_ARB_vertex_attrib_binding");
String vendorStr = (const char*)glGetString( GL_VENDOR );
if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos)
@ -216,6 +224,9 @@ GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
mCurrentVB_Divisor[i] = 0;
}
// Initiailize capabilities to false.
memset(&mCapabilities, 0, sizeof(GLCapabilities));
loadGLCore();
GFXGLEnumTranslate::init();
@ -325,6 +336,7 @@ void GFXGLDevice::resurrect()
GFXVertexBuffer* GFXGLDevice::findVolatileVBO(U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize)
{
PROFILE_SCOPE(GFXGLDevice_findVBPool);
for(U32 i = 0; i < mVolatileVBs.size(); i++)
if ( mVolatileVBs[i]->mNumVerts >= numVerts &&
mVolatileVBs[i]->mVertexFormat.isEqual( *vertexFormat ) &&
@ -333,6 +345,7 @@ GFXVertexBuffer* GFXGLDevice::findVolatileVBO(U32 numVerts, const GFXVertexForma
return mVolatileVBs[i];
// No existing VB, so create one
PROFILE_SCOPE(GFXGLDevice_createVBPool);
StrongRefPtr<GFXGLVertexBuffer> buf(new GFXGLVertexBuffer(GFX, numVerts, vertexFormat, vertSize, GFXBufferTypeVolatile));
buf->registerResourceWithDevice(this);
mVolatileVBs.push_back(buf);
@ -358,6 +371,7 @@ GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts,
GFXBufferType bufferType,
void* data )
{
PROFILE_SCOPE(GFXGLDevice_allocVertexBuffer);
if(bufferType == GFXBufferTypeVolatile)
return findVolatileVBO(numVerts, vertexFormat, vertSize);
@ -523,6 +537,7 @@ inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32
GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat )
{
PROFILE_SCOPE(GFXGLDevice_allocVertexDecl);
typedef Map<void*, GFXGLVertexDecl> GFXGLVertexDeclMap;
static GFXGLVertexDeclMap declMap;
GFXGLVertexDeclMap::Iterator itr = declMap.find( (void*)vertexFormat->getDescription().c_str() ); // description string are interned, safe to use c_str()
@ -855,6 +870,7 @@ void GFXGLDevice::setShader(GFXShader *shader, bool force)
void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
{
PROFILE_SCOPE(GFXGLDevice_setShaderConstBufferInternal);
static_cast<GFXGLShaderConstBuffer*>(buffer)->activate();
}

View file

@ -45,6 +45,18 @@ class GFXGLVertexDecl;
class GFXGLDevice : public GFXDevice
{
public:
struct GLCapabilities
{
bool anisotropicFiltering;
bool bufferStorage;
bool shaderModel5;
bool textureStorage;
bool samplerObjects;
bool copyImage;
bool vertexAttributeBinding;
};
GLCapabilities mCapabilities;
void zombify();
void resurrect();
GFXGLDevice(U32 adapterIndex);

View file

@ -23,6 +23,7 @@
#include "platform/platform.h"
#include "gfx/gl/gfxGLShader.h"
#include "gfx/gl/gfxGLVertexAttribLocation.h"
#include "gfx/gl/gfxGLDevice.h"
#include "core/frameAllocator.h"
#include "core/stream/fileStream.h"
@ -344,6 +345,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* ma
void GFXGLShaderConstBuffer::activate()
{
PROFILE_SCOPE(GFXGLShaderConstBuffer_activate);
mShader->setConstantsFromBuffer(this);
mWasLost = false;
}
@ -394,6 +396,7 @@ void GFXGLShader::clearShaders()
bool GFXGLShader::_init()
{
PROFILE_SCOPE(GFXGLShader_Init);
// Don't initialize empty shaders.
if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() )
return false;
@ -956,7 +959,7 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader,
buffers.push_back( dStrdup( versionDecl ) );
lengths.push_back( dStrlen( versionDecl ) );
if(gglHasExtension(ARB_gpu_shader5))
if(GFXGL->mCapabilities.shaderModel5)
{
const char *extension = "#extension GL_ARB_gpu_shader5 : enable\r\n";
buffers.push_back( dStrdup( extension ) );
@ -1013,6 +1016,7 @@ bool GFXGLShader::initShader( const Torque::Path &file,
bool isVertex,
const Vector<GFXShaderMacro> &macros )
{
PROFILE_SCOPE(GFXGLShader_CompileShader);
GLuint activeShader = glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
if(isVertex)
mVertexShader = activeShader;
@ -1072,6 +1076,7 @@ bool GFXGLShader::initShader( const Torque::Path &file,
/// Returns our list of shader constants, the material can get this and just set the constants it knows about
const Vector<GFXShaderConstDesc>& GFXGLShader::getShaderConstDesc() const
{
PROFILE_SCOPE(GFXGLShader_GetShaderConstants);
return mConstants;
}

View file

@ -39,7 +39,7 @@ GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) :
mDesc(desc),
mCachedHashValue(desc.getHashValue())
{
if( !gglHasExtension(ARB_sampler_objects) )
if( !GFXGL->mCapabilities.samplerObjects )
return;
static Map<GFXSamplerStateDesc, U32> mSamplersMap;
@ -88,6 +88,7 @@ const GFXStateBlockDesc& GFXGLStateBlock::getDesc() const
/// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states.
void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
{
PROFILE_SCOPE(GFXGLStateBlock_Activate);
// Big scary warning copied from Apple docs
// http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/chapter_13_section_2.html#//apple_ref/doc/uid/TP40001987-CH213-SW12
// Don't set a state that's already set. Once a feature is enabled, it does not need to be enabled again.
@ -165,7 +166,7 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
#undef CHECK_TOGGLE_STATE
//sampler objects
if( gglHasExtension(ARB_sampler_objects) )
if( GFXGL->mCapabilities.samplerObjects )
{
for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++)
{

View file

@ -146,7 +146,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 );
if( gglHasExtension(ARB_texture_storage) )
if( GFXGL->mCapabilities.textureStorage )
{
if(binding == GL_TEXTURE_2D)
glTexStorage2D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height );
@ -234,6 +234,7 @@ static void _fastTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8)
{
PROFILE_SCOPE(Swizzle32_Upload);
U8* pboMemory = (U8*)dMalloc(bufSize);
GFX->getDeviceSwizzle32()->ToBuffer(pboMemory, pDL->getBits(0), bufSize);
glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pboMemory );
@ -241,6 +242,7 @@ static void _fastTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
}
else
{
PROFILE_SCOPE(SwizzleNull_Upload);
glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pDL->getBits(0) );
}
@ -262,6 +264,7 @@ static void _slowTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
{
PROFILE_SCOPE(GFXGLTextureManager_loadTexture);
GFXGLTextureObject *texture = static_cast<GFXGLTextureObject*>(aTexture);
AssertFatal(texture->getBinding() == GL_TEXTURE_1D || texture->getBinding() == GL_TEXTURE_2D,
@ -291,6 +294,8 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
{
PROFILE_SCOPE(GFXGLTextureManager_loadTextureDDS);
AssertFatal(!(dds->mFormat == GFXFormatDXT2 || dds->mFormat == GFXFormatDXT4), "GFXGLTextureManager::_loadTexture - OpenGL does not support DXT2 or DXT4 compressed textures");
GFXGLTextureObject* texture = static_cast<GFXGLTextureObject*>(aTexture);
@ -304,10 +309,11 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
glBindTexture(texture->getBinding(), texture->getHandle());
texture->mFormat = dds->mFormat;
U32 numMips = dds->mSurfaces[0]->mMips.size();
if(GFX->getCardProfiler()->queryProfile("GL::Workaround::noManualMips"))
numMips = 1;
for(U32 i = 0; i < numMips; i++)
{
PROFILE_SCOPE(GFXGLTexMan_loadSurface);
if(isCompressedFormat(dds->mFormat))
{
if((!isPow2(dds->getWidth()) || !isPow2(dds->getHeight())) && GFX->getCardProfiler()->queryProfile("GL::Workaround::noCompressedNPoTTextures"))
@ -344,6 +350,7 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, void *raw)
{
PROFILE_SCOPE(GFXGLTextureManager_loadTextureRaw);
if(aTexture->getDepth() < 1)
return false;

View file

@ -96,6 +96,9 @@ void GFXGLTextureObject::unlock(U32 mipLevel)
if(!mLockedRect.bits)
return;
// I know this is in unlock, but in GL we actually do our submission in unlock.
PROFILE_SCOPE(GFXGLTextureObject_lockRT);
PRESERVE_TEXTURE(mBinding);
glBindTexture(mBinding, mHandle);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, mBuffer);
@ -175,6 +178,7 @@ bool GFXGLTextureObject::copyToBmp(GBitmap * bmp)
glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], orig);
PROFILE_START(GFXGLTextureObject_copyToBmp_pixCopy);
for(int i = 0; i < srcPixelCount; ++i)
{
dest[0] = orig[0];
@ -186,6 +190,7 @@ bool GFXGLTextureObject::copyToBmp(GBitmap * bmp)
orig += srcBytesPerPixel;
dest += dstBytesPerPixel;
}
PROFILE_END();
return true;
}
@ -211,7 +216,7 @@ void GFXGLTextureObject::bind(U32 textureUnit)
glBindTexture(mBinding, mHandle);
GFXGL->getOpenglCache()->setCacheBindedTex(textureUnit, mBinding, mHandle);
if( gglHasExtension(ARB_sampler_objects) )
if(GFXGL->mCapabilities.samplerObjects)
return;
GFXGLStateBlockRef sb = mGLDevice->getCurrentStateBlock();
@ -298,8 +303,8 @@ void GFXGLTextureObject::reloadFromCache()
else if(mBinding == GL_TEXTURE_1D)
glTexSubImage1D(mBinding, 0, 0, (mTextureSize.x > 1 ? mTextureSize.x : mTextureSize.y), GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache);
if(GFX->getCardProfiler()->queryProfile("GL::Workaround::needsExplicitGenerateMipmap") && mMipLevels != 1)
glGenerateMipmapEXT(mBinding);
if(mMipLevels != 1)
glGenerateMipmap(mBinding);
delete[] mZombieCache;
mZombieCache = NULL;

View file

@ -410,7 +410,7 @@ void GFXGLTextureTarget::resolveTo(GFXTextureObject* obj)
AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);
if( gglHasExtension(ARB_copy_image) && mTargets[Color0]->isCompatible(glTexture) )
if( GFXGL->mCapabilities.copyImage && mTargets[Color0]->isCompatible(glTexture) )
{
GLenum binding = mTargets[Color0]->getBinding();
binding = (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ? GL_TEXTURE_CUBE_MAP : binding;

View file

@ -78,7 +78,7 @@ void GFXGLVertexBuffer::lock( U32 vertexStart, U32 vertexEnd, void **vertexPtr )
if( mBufferType == GFXBufferTypeVolatile )
{
AssertFatal(vertexStart == 0, "");
if( gglHasExtension(ARB_vertex_attrib_binding) )
if( GFXGL->mCapabilities.vertexAttributeBinding )
{
getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, 0, mBufferOffset, *vertexPtr );
}
@ -136,7 +136,7 @@ void GFXGLVertexBuffer::prepare()
void GFXGLVertexBuffer::prepare(U32 stream, U32 divisor)
{
if( gglHasExtension(ARB_vertex_attrib_binding) )
if( GFXGL->mCapabilities.vertexAttributeBinding )
{
glBindVertexBuffer( stream, mBuffer, mBufferOffset, mVertexSize );
glVertexBindingDivisor( stream, divisor );

View file

@ -15,7 +15,7 @@ void GFXGLVertexDecl::init(const GFXVertexFormat *format)
void GFXGLVertexDecl::prepareVertexFormat() const
{
AssertFatal(mFormat, "GFXGLVertexDecl - Not inited");
if( gglHasExtension(ARB_vertex_attrib_binding) )
if( GFXGL->mCapabilities.vertexAttributeBinding )
{
for ( U32 i=0; i < glVerticesFormat.size(); i++ )
{
@ -36,7 +36,7 @@ void GFXGLVertexDecl::prepareBuffer_old(U32 stream, GLint mBuffer, GLint mDiviso
PROFILE_SCOPE(GFXGLVertexDecl_prepare);
AssertFatal(mFormat, "GFXGLVertexDecl - Not inited");
if( gglHasExtension(ARB_vertex_attrib_binding) )
if( GFXGL->mCapabilities.vertexAttributeBinding )
return;
// Bind the buffer...

View file

@ -78,7 +78,7 @@ void GFXGLWindowTarget::resolveTo(GFXTextureObject* obj)
AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);
if( gglHasExtension(ARB_copy_image) )
if( GFXGL->mCapabilities.copyImage )
{
if(mBackBufferColorTex.getWidth() == glTexture->getWidth()
&& mBackBufferColorTex.getHeight() == glTexture->getHeight()

View file

@ -284,7 +284,8 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
|| type == TypeMatrixPosition
|| type == TypeMatrixRotation
|| type == TypeBox3F
|| type == TypeRectUV )
|| type == TypeRectUV
|| type == TypeRotationF)
{
//TODO: we should actually take strings into account and not chop things up between quotes

View file

@ -30,7 +30,6 @@ ImplementFeatureType( MFT_VertTransform, MFG_Transform, 0, true );
ImplementFeatureType( MFT_TexAnim, MFG_PreTexture, 1.0f, true );
ImplementFeatureType( MFT_Parallax, MFG_PreTexture, 2.0f, true );
ImplementFeatureType( MFT_DiffuseVertColor, MFG_PreTexture, 3.0f, true );
ImplementFeatureType( MFT_AccuScale, MFG_PreTexture, 4.0f, true );
ImplementFeatureType( MFT_AccuDirection, MFG_PreTexture, 4.0f, true );
@ -42,6 +41,7 @@ ImplementFeatureType( MFT_DiffuseMap, MFG_Texture, 2.0f, true );
ImplementFeatureType( MFT_OverlayMap, MFG_Texture, 3.0f, true );
ImplementFeatureType( MFT_DetailMap, MFG_Texture, 4.0f, true );
ImplementFeatureType( MFT_DiffuseColor, MFG_Texture, 5.0f, true );
ImplementFeatureType( MFT_DiffuseVertColor, MFG_Texture, 6.0f, true );
ImplementFeatureType( MFT_AlphaTest, MFG_Texture, 7.0f, true );
ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true );
ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true );

View file

@ -1153,7 +1153,8 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons
// Deferred Shading: Determine Material Info Flags
S32 matInfoFlags =
(mMaterial->mEmissive[stageNum] ? 1 : 0);
(mMaterial->mEmissive[stageNum] ? 1 : 0) | //emissive
(mMaterial->mSubSurface[stageNum] ? 2 : 0); //subsurface
mMaterial->mMatInfoFlags[stageNum] = matInfoFlags / 255.0f;
shaderConsts->setSafe(handles->mMatInfoFlagsSC, mMaterial->mMatInfoFlags[stageNum]);
if( handles->mAccuScaleSC->isValid() )

View file

@ -415,7 +415,7 @@ inline void Box3F::extend(const Point3F & p)
#define EXTEND_AXIS(AXIS) \
if (p.AXIS < minExtents.AXIS) \
minExtents.AXIS = p.AXIS; \
else if (p.AXIS > maxExtents.AXIS) \
if (p.AXIS > maxExtents.AXIS) \
maxExtents.AXIS = p.AXIS;
EXTEND_AXIS(x)

View file

@ -48,5 +48,8 @@
#ifndef _MEASE_H_
#include "math/mEase.h"
#endif
#ifndef MROTATION_H
#include "math/mRotation.h"
#endif
#endif //_MMATH_H_

View file

@ -385,6 +385,8 @@ U32 PolyhedronImpl< Base >::extractFace( U32 plane, IndexType* outIndices, U32 m
// so it should be sufficiently fast to just loop over the original
// set.
U32 indexItr = 0;
do
{
// Add the vertex for the current edge.
@ -392,7 +394,15 @@ U32 PolyhedronImpl< Base >::extractFace( U32 plane, IndexType* outIndices, U32 m
if( idx >= maxOutIndices )
return 0;
outIndices[ idx ++ ] = currentVertex;
++indexItr;
if (indexItr >= 3)
{
outIndices[idx++] = firstEdge->vertex[0];
indexItr = 0;
}
outIndices[idx++] = currentVertex;
// Look for next edge.

View file

@ -0,0 +1,348 @@
//-----------------------------------------------------------------------------
// 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 "math/mRotation.h"
#include "console/console.h"
#include "console/engineAPI.h"
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#endif
//====================================================================
//Eulers setup
//====================================================================
RotationF::RotationF(EulerF _euler, UnitFormat format)
{
set(_euler.x, _euler.y, _euler.z, format);
}
RotationF::RotationF(F32 _x, F32 _y, F32 _z, UnitFormat format)
{
set(_x, _y, _z, format);
}
void RotationF::set(EulerF _euler, UnitFormat format)
{
x = format == Degrees ? mDegToRad(_euler.x) : _euler.x;
y = format == Degrees ? mDegToRad(_euler.y) : _euler.y;
z = format == Degrees ? mDegToRad(_euler.z) : _euler.z;
mRotationType = Euler;
}
void RotationF::set(F32 _x, F32 _y, F32 _z, UnitFormat format)
{
EulerF tempEul;
if (format == Degrees)
{
tempEul.set(mDegToRad(_x), mDegToRad(_y), mDegToRad(_z));
}
else
{
tempEul.set(_x, _y, _z);
}
set(tempEul);
}
//====================================================================
//AxisAngle setup
//====================================================================
RotationF::RotationF(AngAxisF _aa, UnitFormat format)
{
set(_aa, format);
}
void RotationF::set(AngAxisF _aa, UnitFormat format)
{
x = _aa.axis.x;
y = _aa.axis.y;
z = _aa.axis.z;
w = format == Degrees ? mDegToRad(_aa.angle) : _aa.angle;
mRotationType = AxisAngle;
}
//====================================================================
//QuatF setup
//====================================================================
RotationF::RotationF(QuatF _quat)
{
set(_quat);
}
void RotationF::set(QuatF _quat)
{
AngAxisF tmpAA;
tmpAA.set(_quat);
set(tmpAA);
}
//====================================================================
//MatrixF setup
//====================================================================
RotationF::RotationF(MatrixF _mat)
{
set(_mat);
}
void RotationF::set(MatrixF _mat)
{
set(_mat.toEuler());
}
//
inline F32 RotationF::len() const
{
return asEulerF().len();
}
inline void RotationF::interpolate(const RotationF& _from, const RotationF& _to, F32 _factor)
{
QuatF tmpQuat;
tmpQuat.interpolate(_from.asQuatF(), _to.asQuatF(), _factor);
set(tmpQuat);
}
void RotationF::lookAt(const Point3F& _origin, const Point3F& _target, const Point3F& _up)
{
MatrixF mat;
VectorF newForward = _target - _origin;
newForward.normalize();
VectorF up(0.0f, 0.0f, 1.0f);
VectorF axisX;
VectorF axisY = newForward;
VectorF axisZ;
if (_up != VectorF::Zero)
up = _up;
// Validate and normalize input:
F32 lenSq;
lenSq = axisY.lenSquared();
if (lenSq < 0.000001f)
{
//degenerate forward vector
axisY.set(0.0f, 1.0f, 0.0f);
}
else
{
axisY /= mSqrt(lenSq);
}
lenSq = up.lenSquared();
if (lenSq < 0.000001f)
{
//degenerate up vector - too small
up.set(0.0f, 0.0f, 1.0f);
}
else
{
up /= mSqrt(lenSq);
}
if (fabsf(mDot(up, axisY)) > 0.9999f)
{
//degenerate up vector - same as forward
F32 tmp = up.x;
up.x = -up.y;
up.y = up.z;
up.z = tmp;
}
// construct the remaining axes:
mCross(axisY, up, &axisX);
mCross(axisX, axisY, &axisZ);
mat.setColumn(0, axisX);
mat.setColumn(1, axisY);
mat.setColumn(2, axisZ);
set(mat);
}
//========================================================
EulerF RotationF::asEulerF(UnitFormat _format) const
{
if (mRotationType == Euler)
{
if (_format == Degrees)
{
return EulerF(mRadToDeg(x), mRadToDeg(y), mRadToDeg(z));
}
else
{
return EulerF(x, y, z);
}
}
else
{
EulerF returnEuler = asMatrixF().toEuler();
if (_format == Degrees)
{
returnEuler.x = mRadToDeg(returnEuler.x);
returnEuler.y = mRadToDeg(returnEuler.y);
returnEuler.z = mRadToDeg(returnEuler.z);
}
return returnEuler;
}
}
AngAxisF RotationF::asAxisAngle(UnitFormat format) const
{
AngAxisF returnAA;
if (mRotationType == Euler)
{
returnAA.set(EulerF(x, y, z));
}
else
{
returnAA.set(Point3F(x, y, z), w);
}
if (format == Radians)
{
returnAA.angle = mDegToRad(returnAA.angle);
}
return returnAA;
}
MatrixF RotationF::asMatrixF() const
{
MatrixF returnMat;
if (mRotationType == Euler)
{
returnMat.set(EulerF(x, y, z));
}
else
{
AngAxisF aa;
aa.set(Point3F(x, y, z), w);
aa.setMatrix(&returnMat);
}
return returnMat;
}
QuatF RotationF::asQuatF() const
{
QuatF returnQuat;
if (mRotationType == Euler)
{
returnQuat.set(EulerF(x, y, z));
}
else
{
AngAxisF aa;
aa.set(Point3F(x, y, z), w);
returnQuat.set(aa);
}
return returnQuat;
}
void RotationF::normalize()
{
if (mRotationType == Euler)
{
EulerF eul = EulerF(x, y, z);
eul.normalize();
set(eul);
}
else
{
QuatF quat;
quat.set(Point3F(x, y, z), w);
quat.normalize();
set(quat);
}
}
//Testing
#ifdef TORQUE_TESTS_ENABLED
TEST(Maths, RotationF_Calculations)
{
//TODO: implement unit test
};
#endif
DefineConsoleStaticMethod(Rotation, Add, RotationF, (RotationF a, RotationF b), ,
"Adds two rotations together.\n"
"@param a Rotation one."
"@param b Rotation two."
"@returns v sum of both rotations."
"@ingroup Math")
{
return a + b;
}
DefineConsoleStaticMethod(Rotation, Subtract, RotationF, (RotationF a, RotationF b), ,
"Subtracts two rotations.\n"
"@param a Rotation one."
"@param b Rotation two."
"@returns v difference of both rotations."
"@ingroup Math")
{
return a - b;
}
DefineConsoleStaticMethod(Rotation, Interpolate, RotationF, (RotationF a, RotationF b, F32 factor), ,
"Interpolates between two rotations.\n"
"@param a Rotation one."
"@param b Rotation two."
"@param factor The amount to interpolate between the two."
"@returns v, interpolated result."
"@ingroup Math")
{
RotationF result;
result.interpolate(a, b, factor);
return result;
}
DefineConsoleStaticMethod(Rotation, LookAt, RotationF, (Point3F origin, Point3F target, Point3F up),
(Point3F(0, 0, 0), Point3F(0, 0, 0), Point3F(0, 0, 1)),
"Provides a rotation orientation to look at a target from a given position.\n"
"@param origin Position of the object doing the looking."
"@param target Position to be looked at."
"@param up The up angle to orient the rotation."
"@returns v orientation result."
"@ingroup Math")
{
RotationF result;
result.lookAt(origin, target, up);
return result;
}

View file

@ -0,0 +1,465 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef MROTATION_H
#define MROTATION_H
#ifndef _MMATHFN_H_
#include "math/mMathFn.h"
#endif
#ifndef _MPOINT3_H_
#include "math/mPoint3.h"
#endif
#ifndef _MQUAT_H_
#include "math/mQuat.h"
#endif
#ifndef _MMATRIX_H_
#include "math/mMatrix.h"
#endif
#ifndef _MANGAXIS_H_
#include "math/mAngAxis.h"
#endif
//------------------------------------------------------------------------------
/// Rotation Interop Utility class
///
/// Useful for easily handling rotations/orientations in transforms while manipulating or converting between formats.
class RotationF
{
//-------------------------------------- Public data
public:
F32 x; ///< X co-ordinate.
F32 y; ///< Y co-ordinate.
F32 z; ///< Z co-ordinate.
F32 w; ///< W co-ordinate.
enum RotationTypes
{
Euler = 0,
AxisAngle
};
RotationTypes mRotationType;
enum UnitFormat
{
Radians = 0,
Degrees
};
RotationF(); ///< Create an uninitialized point.
RotationF(const RotationF&); ///< Copy constructor.
//
//Eulers
RotationF(EulerF euler, UnitFormat format = Radians);
RotationF(F32 _x, F32 _y, F32 _z, UnitFormat format = Radians);
void set(EulerF euler, UnitFormat format = Radians);
void set(F32 _x, F32 _y, F32 _z, UnitFormat format = Radians);
//As with AxisAngles, we make the assumption here that if not told otherwise, inbound rotations are in Degrees.
RotationF operator=(const EulerF&);
RotationF operator-(const EulerF&) const;
RotationF operator+(const EulerF&) const;
RotationF& operator-=(const EulerF&);
RotationF& operator+=(const EulerF&);
S32 operator==(const EulerF&) const;
S32 operator!=(const EulerF&) const;
//
//AxisAngle
RotationF(AngAxisF aa, UnitFormat format = Radians);
void set(AngAxisF aa, UnitFormat format = Radians);
//As with Eulers, we make the assumption here that if not told otherwise, inbound rotations are in Degrees.
RotationF operator=(const AngAxisF&);
RotationF operator-(const AngAxisF&) const;
RotationF operator+(const AngAxisF&) const;
RotationF& operator-=(const AngAxisF&);
RotationF& operator+=(const AngAxisF&);
S32 operator==(const AngAxisF&) const;
S32 operator!=(const AngAxisF&) const;
//
//Quat
RotationF(QuatF quat);
void set(QuatF _quat);
RotationF operator=(const QuatF&);
RotationF operator-(const QuatF&) const;
RotationF operator+(const QuatF&) const;
RotationF& operator-=(const QuatF&);
RotationF& operator+=(const QuatF&);
S32 operator==(const QuatF&) const;
S32 operator!=(const QuatF&) const;
//
//Matrix
RotationF(MatrixF mat);
void set(MatrixF _mat);
RotationF operator=(const MatrixF&);
RotationF operator-(const MatrixF&) const;
RotationF operator+(const MatrixF&) const;
RotationF& operator-=(const MatrixF&);
RotationF& operator+=(const MatrixF&);
S32 operator==(const MatrixF&) const;
S32 operator!=(const MatrixF&) const;
//
void interpolate(const RotationF& _pt1, const RotationF& _pt2, F32 _factor);
void lookAt(const Point3F& _origin, const Point3F& _target, const Point3F& _up = Point3F(0, 0, 1));
F32 len() const;
void normalize();
//Non-converting operators
S32 operator ==(const RotationF &) const;
S32 operator !=(const RotationF &) const;
RotationF operator+(const RotationF&) const;
RotationF& operator+=(const RotationF&);
RotationF operator-(const RotationF&) const;
RotationF& operator-=(const RotationF&);
RotationF& operator=(const RotationF&);
//Conversion stuffs
EulerF asEulerF(UnitFormat format = Radians) const;
AngAxisF asAxisAngle(UnitFormat format = Radians) const;
MatrixF asMatrixF() const;
QuatF asQuatF() const;
};
inline RotationF::RotationF()
{
x = 0;
y = 0;
z = 0;
w = 0;
mRotationType = AxisAngle;
}
inline RotationF::RotationF(const RotationF& _copy)
: x(_copy.x), y(_copy.y), z(_copy.z), w(_copy.w), mRotationType(_copy.mRotationType)
{}
inline int RotationF::operator ==(const RotationF& _rotation) const
{
return (x == _rotation.x && y == _rotation.y && z == _rotation.z && w == _rotation.w);
}
inline int RotationF::operator !=(const RotationF& _rotation) const
{
return (x != _rotation.x || y != _rotation.y || z != _rotation.z || w != _rotation.w);
}
//When it comes to actually trying to add rotations, we, in fact, actually multiply their data together.
//Since we're specifically operating on usability for RotationF, we'll operate on this, rather than the literal addition of the values
inline RotationF& RotationF::operator +=(const RotationF& _rotation)
{
if (mRotationType == Euler)
{
x += _rotation.x;
y += _rotation.y;
z += _rotation.z;
}
else
{
MatrixF tempMat = asMatrixF();
MatrixF tempMatAdd = _rotation.asMatrixF();
tempMat.mul(tempMatAdd);
this->set(tempMat);
}
return *this;
}
inline RotationF RotationF::operator +(const RotationF& _rotation) const
{
RotationF result = *this;
if (mRotationType == Euler)
{
result.x += _rotation.x;
result.y += _rotation.y;
result.z += _rotation.z;
}
else
{
MatrixF tempMat = asMatrixF();
MatrixF tempMatAdd = _rotation.asMatrixF();
tempMat.mul(tempMatAdd);
result.set(tempMat);
}
return result;
}
//Much like addition, when subtracting, we're not literally subtracting the values, but infact multiplying the inverse.
//This subtracts the rotation angles to get the difference
inline RotationF& RotationF::operator -=(const RotationF& _rotation)
{
if (mRotationType == Euler)
{
x -= _rotation.x;
y -= _rotation.y;
z -= _rotation.z;
}
else
{
MatrixF tempMat = asMatrixF();
MatrixF tempMatAdd = _rotation.asMatrixF();
tempMatAdd.inverse();
tempMat.mul(tempMatAdd);
this->set(tempMat);
}
return *this;
}
inline RotationF RotationF::operator -(const RotationF& _rotation) const
{
RotationF result = *this;
if (mRotationType == Euler)
{
result.x += _rotation.x;
result.y += _rotation.y;
result.z += _rotation.z;
}
else
{
MatrixF tempMat = asMatrixF();
MatrixF tempMatAdd = _rotation.asMatrixF();
tempMatAdd.inverse();
tempMat.mul(tempMatAdd);
result.set(tempMat);
}
return result;
}
inline RotationF& RotationF::operator =(const RotationF& _rotation)
{
x = _rotation.x;
y = _rotation.y;
z = _rotation.z;
w = _rotation.w;
mRotationType = _rotation.mRotationType;
return *this;
}
//====================================================================
// Euler operators
//====================================================================
inline RotationF RotationF::operator=(const EulerF& _euler)
{
return RotationF(_euler, Radians);
}
inline RotationF RotationF::operator-(const EulerF& _euler) const
{
RotationF temp = *this;
temp -= RotationF(_euler, Radians);
return temp;
}
inline RotationF RotationF::operator+(const EulerF& _euler) const
{
RotationF temp = *this;
temp += RotationF(_euler, Radians);
return temp;
}
inline RotationF& RotationF::operator-=(const EulerF& _euler)
{
*this -= RotationF(_euler, Radians);
return *this;
}
inline RotationF& RotationF::operator+=(const EulerF& _euler)
{
*this += RotationF(_euler, Radians);
return *this;
}
inline S32 RotationF::operator==(const EulerF& _euler) const
{
return *this == RotationF(_euler);
}
inline S32 RotationF::operator!=(const EulerF& _euler) const
{
return *this != RotationF(_euler);
}
//====================================================================
// AxisAngle operators
//====================================================================
inline RotationF RotationF::operator=(const AngAxisF& _aa)
{
return RotationF(_aa, Radians);
}
inline RotationF RotationF::operator-(const AngAxisF& _aa) const
{
RotationF temp = *this;
temp -= RotationF(_aa, Radians);
return temp;
}
inline RotationF RotationF::operator+(const AngAxisF& _aa) const
{
RotationF temp = *this;
temp += RotationF(_aa, Radians);
return temp;
}
inline RotationF& RotationF::operator-=(const AngAxisF& _aa)
{
*this -= RotationF(_aa, Radians);
return *this;
}
inline RotationF& RotationF::operator+=(const AngAxisF& _aa)
{
*this += RotationF(_aa, Radians);
return *this;
}
inline S32 RotationF::operator==(const AngAxisF& _aa) const
{
return *this == RotationF(_aa);
}
inline S32 RotationF::operator!=(const AngAxisF& _aa) const
{
return *this != RotationF(_aa);
}
//====================================================================
// QuatF operators
//====================================================================
inline RotationF RotationF::operator=(const QuatF& _quat)
{
return RotationF(_quat);
}
inline RotationF RotationF::operator-(const QuatF& _quat) const
{
RotationF temp = *this;
temp -= RotationF(_quat);
return temp;
}
inline RotationF RotationF::operator+(const QuatF& _quat) const
{
RotationF temp = *this;
temp += RotationF(_quat);
return temp;
}
inline RotationF& RotationF::operator-=(const QuatF& _quat)
{
*this -= RotationF(_quat);
return *this;
}
inline RotationF& RotationF::operator+=(const QuatF& _quat)
{
*this += RotationF(_quat);
return *this;
}
inline S32 RotationF::operator==(const QuatF& _quat) const
{
return *this == RotationF(_quat);
}
inline S32 RotationF::operator!=(const QuatF& _quat) const
{
return *this != RotationF(_quat);
}
//====================================================================
// MatrixF operators
//====================================================================
inline RotationF RotationF::operator=(const MatrixF& _mat)
{
return RotationF(_mat);
}
inline RotationF RotationF::operator-(const MatrixF& _mat) const
{
RotationF temp = *this;
temp -= RotationF(_mat);
return temp;
}
inline RotationF RotationF::operator+(const MatrixF& _mat) const
{
RotationF temp = *this;
temp += RotationF(_mat);
return temp;
}
inline RotationF& RotationF::operator-=(const MatrixF& _mat)
{
*this -= RotationF(_mat);
return *this;
}
inline RotationF& RotationF::operator+=(const MatrixF& _mat)
{
*this += RotationF(_mat);
return *this;
}
inline S32 RotationF::operator==(const MatrixF& _mat) const
{
return *this == RotationF(_mat);
}
inline S32 RotationF::operator!=(const MatrixF& _mat) const
{
return *this != RotationF(_mat);
}
#endif // MROTATION_H

View file

@ -149,6 +149,20 @@ inline bool mathRead(Stream& stream, EaseF* e)
return success;
}
inline bool mathRead(Stream& stream, RotationF* e)
{
bool success = stream.read(&e->x);
success &= stream.read(&e->y);
success &= stream.read(&e->z);
success &= stream.read(&e->w);
U32 rotType;
success &= stream.read(&rotType);
e->mRotationType = (RotationF::RotationTypes)rotType;
return success;
}
//------------------------------------------------------------------------------
//-------------------------------------- WRITING
//
@ -263,5 +277,15 @@ inline bool mathWrite(Stream& stream, const EaseF& e)
return success;
}
inline bool mathWrite(Stream& stream, const RotationF& e)
{
bool success = stream.write(e.x);
success &= stream.write(e.y);
success &= stream.write(e.z);
success &= stream.write(e.w);
success &= stream.write(e.mRotationType);
return success;;
}
#endif //_MATHIO_H_

View file

@ -36,7 +36,7 @@
#include "math/mRandom.h"
#include "math/mEase.h"
#include "math/mathUtils.h"
#include "math/mRotation.h"
#include "core/strings/stringUnit.h"
IMPLEMENT_SCOPE( MathTypes, Math,, "" );
@ -113,7 +113,14 @@ IMPLEMENT_STRUCT( EaseF,
EaseF, MathTypes,
"" )
END_IMPLEMENT_STRUCT;
IMPLEMENT_STRUCT(RotationF,
RotationF, MathTypes,
"")
FIELD(x, x, 1, "X coordinate.")
FIELD(y, y, 1, "Y coordinate.")
FIELD(z, z, 1, "Z coordinate.")
FIELD(w, w, 1, "W coordinate.")
END_IMPLEMENT_STRUCT;
//-----------------------------------------------------------------------------
// TypePoint2I
@ -572,6 +579,55 @@ ConsoleSetType( TypeEaseF )
}
}
//-----------------------------------------------------------------------------
// TypeRotationF
//-----------------------------------------------------------------------------
ConsoleType(RotationF, TypeRotationF, RotationF, "")
ImplementConsoleTypeCasters( TypeRotationF, RotationF )
ConsoleGetType(TypeRotationF)
{
RotationF *pt = (RotationF *)dptr;
static const U32 bufSize = 256;
char* returnBuffer = Con::getReturnBuffer(bufSize);
EulerF out = pt->asEulerF(RotationF::Degrees);
dSprintf(returnBuffer, bufSize, "%g %g %g", out.x, out.y, out.z);
return returnBuffer;
}
ConsoleSetType(TypeRotationF)
{
if (argc == 1)
{
U32 elements = StringUnit::getUnitCount(argv[0], " \t\n");
if (elements == 3)
{
EulerF in;
dSscanf(argv[0], "%g %g %g", &in.x, &in.y, &in.z);
((RotationF *)dptr)->set(in, RotationF::Degrees);
}
else
{
AngAxisF in;
dSscanf(argv[0], "%g %g %g %g", &in.axis.x, &in.axis.y, &in.axis.z, &in.angle);
((RotationF *)dptr)->set(in, RotationF::Degrees);
}
}
else if (argc == 3)
{
EulerF in(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2]));
((RotationF *)dptr)->set(in, RotationF::Degrees);
}
else if (argc == 4)
{
AngAxisF in(Point3F(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2])), dAtof(argv[3]));
((RotationF *)dptr)->set(in, RotationF::Degrees);
}
else
Con::printf("RotationF must be set as { x, y, z, w } or \"x y z w\"");
}
//-----------------------------------------------------------------------------

View file

@ -43,7 +43,7 @@ class Box3F;
class EaseF;
class AngAxisF;
class TransformF;
class RotationF;
DECLARE_SCOPE( MathTypes );
@ -60,6 +60,7 @@ DECLARE_STRUCT( AngAxisF );
DECLARE_STRUCT( TransformF );
DECLARE_STRUCT( Box3F );
DECLARE_STRUCT( EaseF );
DECLARE_STRUCT(RotationF);
// Legacy console types.
@ -77,6 +78,6 @@ DefineConsoleType( TypeAngAxisF, AngAxisF )
DefineConsoleType( TypeTransformF, TransformF )
DefineConsoleType( TypeBox3F, Box3F )
DefineConsoleType( TypeEaseF, EaseF )
DefineConsoleType(TypeRotationF, RotationF)
#endif

View file

@ -30,7 +30,6 @@
#include "platform/profiler.h"
#include "core/tAlgorithm.h"
#include "gfx/gfxDevice.h"
namespace MathUtils
{
@ -1450,8 +1449,6 @@ void makeProjection( MatrixF *outMatrix,
F32 farPlane,
bool gfxRotate )
{
bool isGL = GFX->getAdapterType() == OpenGL;
Point4F row;
row.x = 2.0*nearPlane / (right-left);
row.y = 0.0;
@ -1467,13 +1464,13 @@ void makeProjection( MatrixF *outMatrix,
row.x = (left+right) / (right-left);
row.y = (top+bottom) / (top-bottom);
row.z = isGL ? -(farPlane + nearPlane) / (farPlane - nearPlane) : farPlane / (nearPlane - farPlane);
row.z = farPlane / (nearPlane - farPlane);
row.w = -1.0;
outMatrix->setRow( 2, row );
row.x = 0.0;
row.y = 0.0;
row.z = isGL ? 2 * nearPlane * farPlane / (nearPlane - farPlane) : nearPlane * farPlane / (nearPlane - farPlane);
row.z = nearPlane * farPlane / (nearPlane - farPlane);
row.w = 0.0;
outMatrix->setRow( 3, row );
@ -1494,8 +1491,6 @@ void makeOrthoProjection( MatrixF *outMatrix,
F32 farPlane,
bool gfxRotate )
{
bool isGL = GFX->getAdapterType() == OpenGL;
Point4F row;
row.x = 2.0f / (right - left);
row.y = 0.0f;
@ -1513,15 +1508,15 @@ void makeOrthoProjection( MatrixF *outMatrix,
row.y = 0.0f;
row.w = 0.0f;
// This needs to be modified to work with OpenGL (d3d has 0..1
// projection for z, vs -1..1 in OpenGL)
row.z = isGL ? 2.0f / (nearPlane - farPlane) : 1.0f / (nearPlane - farPlane);
//Unlike D3D, which has a 0-1 range, OpenGL uses a -1-1 range.
//However, epoxy internally handles the swap, so the math here is the same for both APIs
row.z = 1.0f / (nearPlane - farPlane);
outMatrix->setRow( 2, row );
row.x = (left + right) / (left - right);
row.y = (top + bottom) / (bottom - top);
row.z = isGL ? (nearPlane + farPlane) / (nearPlane - farPlane) : nearPlane / (nearPlane - farPlane);
row.z = nearPlane / (nearPlane - farPlane);
row.w = 1.0f;
outMatrix->setRow( 3, row );

View file

@ -145,6 +145,17 @@ DefineConsoleFunction(NavMeshUpdateAroundObject, void, (S32 objid, bool remove),
obj->enableCollision();
}
DefineConsoleFunction(NavMeshIgnore, void, (S32 objid, bool _ignore), (0, true),
"@brief Flag this object as not generating a navmesh result.")
{
SceneObject *obj;
if(!Sim::findObject(objid, obj))
return;
obj->mPathfindingIgnore = _ignore;
}
DefineConsoleFunction(NavMeshUpdateOne, void, (S32 meshid, S32 objid, bool remove), (0, 0, false),
"@brief Update all tiles in a given NavMesh that intersect the given object's world box.")
{
@ -839,6 +850,7 @@ void NavMesh::buildNextTile()
static void buildCallback(SceneObject* object,void *key)
{
SceneContainer::CallbackInfo* info = reinterpret_cast<SceneContainer::CallbackInfo*>(key);
if (!object->mPathfindingIgnore)
object->buildPolyList(info->context,info->polyList,info->boundingBox,info->boundingSphere);
}
@ -861,7 +873,7 @@ unsigned char *NavMesh::buildTileData(const Tile &tile, TileData &data, U32 &dat
data.geom.clear();
info.polyList = &data.geom;
info.key = this;
getContainer()->findObjects(box, StaticShapeObjectType | TerrainObjectType, buildCallback, &info);
getContainer()->findObjects(box, StaticObjectType | DynamicShapeObjectType, buildCallback, &info);
// Parse water objects into the same list, but remember how much geometry was /not/ water.
U32 nonWaterVertCount = data.geom.getVertCount();

View file

@ -184,40 +184,63 @@ static const U32 convertUTF16toUTF8DoubleNULL(const UTF16 *unistring, UTF8 *out
//
bool FileDialog::Execute()
{
String suffix;
String strippedFilters;
U32 filtersCount = StringUnit::getUnitCount(mData.mFilters, "|");
for (U32 i = 1; i < filtersCount; ++i)
{
//The first of each pair is the name, which we'll skip because NFD doesn't support named filters atm
const char *filter = StringUnit::getUnit(mData.mFilters, i, "|");
String filter = StringUnit::getUnit(mData.mFilters, i, "|");
if (!dStrcmp(filter, "*.*"))
if (!dStrcmp(filter.c_str(), "*.*"))
continue;
U32 c = 2;
const char* tmpchr = &filter[c];
String tString = String(tmpchr);
tString.ToLower(tString);
suffix += tString;
suffix += String(",");
suffix += tString.ToUpper(tString);
U32 subFilterCount = StringUnit::getUnitCount(filter, ";");
//if we have a 'super filter', break it down to sub-options as well
if (subFilterCount > 1)
{
String suffixFilter;
String subFilters;
for (U32 f = 0; f < subFilterCount; ++f)
{
String subFilter = StringUnit::getUnit(filter, f, ";");
suffixFilter += String::ToLower(subFilter) + "," + String::ToUpper(subFilter) + ",";
subFilters += String::ToLower(subFilter) + "," + String::ToUpper(subFilter) + ";";
}
suffixFilter = suffixFilter.substr(0, suffixFilter.length() - 1);
suffixFilter += ";";
strippedFilters += suffixFilter + subFilters;
}
else //otherwise, just add the filter
{
strippedFilters += String::ToLower(filter) + "," + String::ToUpper(filter) + ";";
}
++i;
if (i < filtersCount-2)
suffix += String(";");
if (i < filtersCount - 2)
strippedFilters += String(";");
}
String strippedFilters = suffix;
strippedFilters.replace(";",",");
strippedFilters += String(";") + suffix;
//strip the last character, if it's unneeded
if (strippedFilters.endsWith(";"))
{
strippedFilters = strippedFilters.substr(0, strippedFilters.length() - 1);
}
strippedFilters.replace("*.", "");
// Get the current working directory, so we can back up to it once Windows has
// done its craziness and messed with it.
StringTableEntry cwd = Platform::getCurrentDirectory();
if (mData.mDefaultPath == StringTable->lookup("") || !Platform::isDirectory(mData.mDefaultPath))
mData.mDefaultPath = cwd;
String rootDir = String(cwd);
// Execute Dialog (Blocking Call)
nfdchar_t *outPath = NULL;
nfdpathset_t pathSet;
@ -226,6 +249,7 @@ bool FileDialog::Execute()
String defaultPath = String(mData.mDefaultPath);
#if defined(TORQUE_OS_WIN)
defaultPath.replace("/", "\\");
rootDir.replace("/", "\\");
#endif
if (mData.mStyle & FileDialogData::FDS_OPEN)
@ -235,6 +259,15 @@ bool FileDialog::Execute()
else if (mData.mStyle & FileDialogData::FDS_MULTIPLEFILES)
result = NFD_OpenDialogMultiple(strippedFilters.c_str(), defaultPath.c_str(), &pathSet);
if (result == NFD_CANCEL)
{
return false;
}
String resultPath = String(outPath).replace(rootDir, String(""));
resultPath = resultPath.replace(0, 1, String("")).c_str(); //kill '\\' prefix
resultPath = resultPath.replace(String("\\"), String("/"));
// Did we select a file?
if (result != NFD_OKAY)
{
@ -245,7 +278,7 @@ bool FileDialog::Execute()
if (mData.mStyle & FileDialogData::FDS_OPEN || mData.mStyle & FileDialogData::FDS_SAVE)
{
// Single file selection, do it the easy way
mData.mFile = StringTable->insert(outPath);
mData.mFile = Platform::makeRelativePathName(resultPath.c_str(), NULL);
}
else if (mData.mStyle & FileDialogData::FDS_MULTIPLEFILES)
{
@ -265,14 +298,13 @@ bool FileDialog::Execute()
else
{
//nope, just one file, so set it as normal
setDataField(StringTable->insert("files"), "0", outPath);
setDataField(StringTable->insert("files"), "0", Platform::makeRelativePathName(resultPath.c_str(), NULL));
setDataField(StringTable->insert("fileCount"), NULL, "1");
}
}
// Return success.
return true;
}
DefineEngineMethod(FileDialog, Execute, bool, (), ,

View file

@ -144,6 +144,7 @@ SceneObject::SceneObject()
mIsScopeAlways = false;
mAccuTex = NULL;
mPathfindingIgnore = false;
}
//-----------------------------------------------------------------------------

View file

@ -371,6 +371,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
SceneObject();
virtual ~SceneObject();
bool mPathfindingIgnore;
/// Triggered when a SceneObject onAdd is called.
static Signal< void( SceneObject* ) > smSceneObjectAdd;

View file

@ -1194,7 +1194,10 @@ void DiffuseVertColorFeatureGLSL::processPix( Vector<ShaderComponent*> &compon
}
MultiLine* meta = new MultiLine;
meta->addStatement( new GenOp( " @;\r\n", assignColor( vertColor, Material::Mul ) ) );
if (fd.features[MFT_isDeferred])
meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1)));
else
meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul)));
output = meta;
}
@ -2805,7 +2808,7 @@ void DeferredSkyGLSL::processVert( Vector<ShaderComponent*> &componentList,
{
Var *outPosition = (Var*)LangElement::find( "gl_Position" );
MultiLine *meta = new MultiLine;
meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) );
//meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) );
output = meta;
}

View file

@ -1258,7 +1258,10 @@ void DiffuseVertColorFeatureHLSL::processPix( Vector<ShaderComponent*> &compon
}
MultiLine* meta = new MultiLine;
meta->addStatement( new GenOp( " @;\r\n", assignColor( vertColor, Material::Mul ) ) );
if (fd.features[MFT_isDeferred])
meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1)));
else
meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul)));
output = meta;
}
@ -3000,7 +3003,7 @@ void DeferredSkyHLSL::processVert( Vector<ShaderComponent*> &componentList,
{
Var *outPosition = (Var*)LangElement::find( "hpos" );
MultiLine *meta = new MultiLine;
meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) );
//meta->addStatement( new GenOp( " @.w = @.z;\r\n", outPosition, outPosition ) );
output = meta;
}