diff --git a/Engine/source/T3D/aiPlayer.cpp b/Engine/source/T3D/aiPlayer.cpp index 31ada9970..a20f7a851 100644 --- a/Engine/source/T3D/aiPlayer.cpp +++ b/Engine/source/T3D/aiPlayer.cpp @@ -438,7 +438,7 @@ bool AIPlayer::getAIMove(Move *movePtr) // Replicate the trigger state into the move so that // triggers can be controlled from scripts. - for( S32 i = 0; i < MaxTriggerKeys; i++ ) + for( U32 i = 0; i < MaxMountedImages; i++ ) movePtr->trigger[i] = getImageTriggerState(i); mLastLocation = location; @@ -703,7 +703,7 @@ bool AIPlayer::checkInFoV(GameBase* target, F32 camFov, bool _checkEnabled) // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); - return (dot > camFov); + return (dot > mCos(camFov)); } DefineEngineMethod(AIPlayer, checkInFoV, bool, (ShapeBase* obj, F32 fov, bool checkEnabled), (NULL, 45.0f, false), diff --git a/Engine/source/T3D/fps/guiShapeNameHud.cpp b/Engine/source/T3D/fps/guiShapeNameHud.cpp index 9ec1afac4..0609bbd0e 100644 --- a/Engine/source/T3D/fps/guiShapeNameHud.cpp +++ b/Engine/source/T3D/fps/guiShapeNameHud.cpp @@ -182,9 +182,9 @@ void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect) cam.getColumn(3, &camPos); cam.getColumn(1, &camDir); - F32 camFov; - conn->getControlCameraFov(&camFov); - camFov = mDegToRad(camFov) / 2; + F32 camFovCos; + conn->getControlCameraFov(&camFovCos); + camFovCos = mCos(mDegToRad(camFovCos) / 2); // Visible distance info & name fading F32 visDistance = gClientSceneGraph->getVisibleDistance(); @@ -236,7 +236,7 @@ void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect) // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); - if (dot < camFov) + if (dot < camFovCos) continue; // Test to see if it's behind something, and we want to diff --git a/Engine/source/T3D/fx/explosion.cpp b/Engine/source/T3D/fx/explosion.cpp index f23400232..2468dd181 100644 --- a/Engine/source/T3D/fx/explosion.cpp +++ b/Engine/source/T3D/fx/explosion.cpp @@ -606,7 +606,7 @@ void ExplosionData::packData(BitStream* stream) } U32 count; for(count = 0; count < EC_NUM_TIME_KEYS; count++) - if(times[i] >= 1) + if(times[count] >= 1) break; count++; if(count > EC_NUM_TIME_KEYS) diff --git a/Engine/source/T3D/fx/particle.cpp b/Engine/source/T3D/fx/particle.cpp index 5b794748e..bf9e987f8 100644 --- a/Engine/source/T3D/fx/particle.cpp +++ b/Engine/source/T3D/fx/particle.cpp @@ -355,7 +355,7 @@ bool ParticleData::protectedSetSizes( void *object, const char *index, const cha U32 i; if (!index) - i = 0; + return (val >= 0.f && val <= MaxParticleSize); else i = dAtoui(index); @@ -371,7 +371,7 @@ bool ParticleData::protectedSetTimes( void *object, const char *index, const cha U32 i; if (!index) - i = 0; + return (val >= 0.f && val <= 1.f); else i = dAtoui(index); diff --git a/Engine/source/T3D/fx/particleEmitter.cpp b/Engine/source/T3D/fx/particleEmitter.cpp index b40148cea..4e4f9728b 100644 --- a/Engine/source/T3D/fx/particleEmitter.cpp +++ b/Engine/source/T3D/fx/particleEmitter.cpp @@ -1825,22 +1825,22 @@ void ParticleEmitter::setupOriented( Particle *part, lVerts->point = start + crossDir; lVerts->color = partCol; // Here and below, we copy UVs from particle datablock's texCoords (oriented) - lVerts->texCoord = part->dataBlock->texCoords[0]; + lVerts->texCoord = part->dataBlock->texCoords[1]; ++lVerts; lVerts->point = start - crossDir; lVerts->color = partCol; - lVerts->texCoord = part->dataBlock->texCoords[1]; + lVerts->texCoord = part->dataBlock->texCoords[2]; ++lVerts; lVerts->point = end - crossDir; lVerts->color = partCol; - lVerts->texCoord = part->dataBlock->texCoords[2]; + lVerts->texCoord = part->dataBlock->texCoords[3]; ++lVerts; lVerts->point = end + crossDir; lVerts->color = partCol; - lVerts->texCoord = part->dataBlock->texCoords[3]; + lVerts->texCoord = part->dataBlock->texCoords[0]; ++lVerts; } diff --git a/Engine/source/T3D/gameFunctions.cpp b/Engine/source/T3D/gameFunctions.cpp index e16acf1ec..d92a0259e 100644 --- a/Engine/source/T3D/gameFunctions.cpp +++ b/Engine/source/T3D/gameFunctions.cpp @@ -239,7 +239,7 @@ void GameUpdateCameraFov() F32 delta = time - sLastCameraUpdateTime; // snap zoom? - if((sZoomSpeed == 0) || (delta <= 0.f)) + if((sZoomSpeed == 0) || (delta <= 0.0f)) sCameraFov = sTargetFov; else { diff --git a/Engine/source/T3D/lightFlareData.cpp b/Engine/source/T3D/lightFlareData.cpp index 8cbad24fc..50c2b069b 100644 --- a/Engine/source/T3D/lightFlareData.cpp +++ b/Engine/source/T3D/lightFlareData.cpp @@ -26,16 +26,18 @@ #include "core/stream/bitStream.h" #include "console/engineAPI.h" #include "lighting/lightInfo.h" +#include "lighting/lightQuery.h" #include "math/mathUtils.h" #include "math/mathIO.h" #include "scene/sceneRenderState.h" #include "gfx/gfxOcclusionQuery.h" #include "gfx/gfxDrawUtil.h" +#include "gfx/gfxTextureManager.h" #include "renderInstance/renderPassManager.h" #include "T3D/gameBase/gameConnection.h" #include "T3D/gameBase/processList.h" #include "collision/collision.h" - +#include "lighting/lightManager.h" const U32 LightFlareData::LosMask = STATIC_COLLISION_TYPEMASK | ShapeBaseObjectType | @@ -45,8 +47,6 @@ const U32 LightFlareData::LosMask = STATIC_COLLISION_TYPEMASK | LightFlareState::~LightFlareState() { - delete occlusionQuery; - delete fullPixelQuery; } void LightFlareState::clear() @@ -59,8 +59,6 @@ void LightFlareState::clear() lightInfo = NULL; worldRadius = -1.0f; occlusion = -1.0f; - occlusionQuery = NULL; - fullPixelQuery = NULL; } Point3F LightFlareData::sBasePoints[] = @@ -296,47 +294,39 @@ bool LightFlareData::_testVisibility(const SceneRenderState *state, LightFlareSt // for one-shot initialization of LightFlareState if ( useOcclusionQuery ) { - if ( flareState->occlusionQuery == NULL ) - flareState->occlusionQuery = GFX->createOcclusionQuery(); - if ( flareState->fullPixelQuery == NULL ) - flareState->fullPixelQuery = GFX->createOcclusionQuery(); - // Always treat light as onscreen if using HOQ // it will be faded out if offscreen anyway. onScreen = true; - - // NOTE: These queries frame lock us as we block to get the - // results. This is ok as long as long as we're not too GPU - // bound... else we waste CPU time here waiting for it when - // we could have been doing other CPU work instead. + needsRaycast = false; // Test the hardware queries for rendered pixels. U32 pixels = 0, fullPixels = 0; - GFXOcclusionQuery::OcclusionQueryStatus status = flareState->occlusionQuery->getStatus( true, &pixels ); - flareState->fullPixelQuery->getStatus( true, &fullPixels ); - if ( status != GFXOcclusionQuery::Occluded && fullPixels != 0 ) + GFXOcclusionQuery::OcclusionQueryStatus status; + flareState->occlusionQuery.getLastStatus( false, &status, &pixels ); + flareState->fullPixelQuery.getLastStatus( false, NULL, &fullPixels ); + + if ( status == GFXOcclusionQuery::NotOccluded && fullPixels != 0 ) *outOcclusionFade = mClampF( (F32)pixels / (F32)fullPixels, 0.0f, 1.0f ); - // If we got a result then we don't need to fallback to the raycast. - if ( status != GFXOcclusionQuery::Unset ) - needsRaycast = false; - - // Setup the new queries. - RenderPassManager *rpm = state->getRenderPass(); - OccluderRenderInst *ri = rpm->allocInst(); - ri->type = RenderPassManager::RIT_Occluder; - ri->query = flareState->occlusionQuery; - ri->query2 = flareState->fullPixelQuery; - ri->isSphere = true; - ri->position = lightPos; - if ( isVectorLight && flareState->worldRadius > 0.0f ) - ri->scale.set( flareState->worldRadius ); - else - ri->scale.set( mOcclusionRadius ); - ri->orientation = rpm->allocUniqueXform( lightInfo->getTransform() ); + if( !flareState->occlusionQuery.isWaiting() ) + { + // Setup the new queries. + RenderPassManager *rpm = state->getRenderPass(); + OccluderRenderInst *ri = rpm->allocInst(); + ri->type = RenderPassManager::RIT_Occluder; + ri->query = flareState->occlusionQuery.getQuery(); + ri->query2 = flareState->fullPixelQuery.getQuery(); + ri->isSphere = true; + ri->position = lightPos; + if ( isVectorLight && flareState->worldRadius > 0.0f ) + ri->scale.set( flareState->worldRadius ); + else + ri->scale.set( mOcclusionRadius ); + ri->orientation = rpm->allocUniqueXform( lightInfo->getTransform() ); - // Submit the queries. - state->getRenderPass()->addInst( ri ); + // Submit the queries. + state->getRenderPass()->addInst( ri ); + } } const Point3F &camPos = state->getCameraPosition(); diff --git a/Engine/source/T3D/lightFlareData.h b/Engine/source/T3D/lightFlareData.h index a450d4e56..333bf1bf5 100644 --- a/Engine/source/T3D/lightFlareData.h +++ b/Engine/source/T3D/lightFlareData.h @@ -41,12 +41,14 @@ #ifndef _GFXSTATEBLOCK_H_ #include "gfx/gfxStateBlock.h" #endif +#ifndef _GFXOCCLUSIONQUERY_H_ +#include "gfx/gfxOcclusionQuery.h" +#endif class LightInfo; struct ObjectRenderInst; class SceneRenderState; class BaseMatInstance; -class GFXOcclusionQuery; struct LightFlareState { @@ -65,8 +67,8 @@ struct LightFlareState bool visible; F32 occlusion; GFXVertexBufferHandle vertBuffer; - GFXOcclusionQuery *occlusionQuery; - GFXOcclusionQuery *fullPixelQuery; + GFXOcclusionQueryHandle occlusionQuery; + GFXOcclusionQueryHandle fullPixelQuery; }; class LightFlareData : public SimDataBlock diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 241be2c2f..f9278e62b 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -6152,13 +6152,16 @@ U32 Player::packUpdate(NetConnection *con, U32 mask, BitStream *stream) stream->writeInt((S32)len, 13); } stream->writeFloat(mRot.z / M_2PI_F, 7); - stream->writeSignedFloat(mHead.x / mDataBlock->maxLookAngle, 6); + stream->writeSignedFloat(mHead.x / (mDataBlock->maxLookAngle - mDataBlock->minLookAngle), 6); stream->writeSignedFloat(mHead.z / mDataBlock->maxFreelookAngle, 6); delta.move.pack(stream); stream->writeFlag(!(mask & NoWarpMask)); } // Ghost need energy to predict reliably - stream->writeFloat(getEnergyLevel() / mDataBlock->maxEnergy,EnergyLevelBits); + if (mDataBlock->maxEnergy > 0.f) + stream->writeFloat(getEnergyLevel() / mDataBlock->maxEnergy, EnergyLevelBits); + else + stream->writeFloat(0.f, EnergyLevelBits); return retMask; } @@ -6250,7 +6253,7 @@ void Player::unpackUpdate(NetConnection *con, BitStream *stream) rot.y = rot.x = 0.0f; rot.z = stream->readFloat(7) * M_2PI_F; - mHead.x = stream->readSignedFloat(6) * mDataBlock->maxLookAngle; + mHead.x = stream->readSignedFloat(6) * (mDataBlock->maxLookAngle - mDataBlock->minLookAngle); mHead.z = stream->readSignedFloat(6) * mDataBlock->maxFreelookAngle; delta.move.unpack(stream); diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index fc0f76998..b6ba1d96a 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -940,8 +940,6 @@ ShapeBase::ShapeBase() for (i = 0; i < MaxTriggerKeys; i++) mTrigger[i] = false; - - mWeaponCamShake = NULL; } @@ -1063,15 +1061,7 @@ void ShapeBase::onRemove() if ( isClientObject() ) { - mCubeReflector.unregisterReflector(); - - if ( mWeaponCamShake ) - { - if ( mWeaponCamShake->isAdded ) - gCamFXMgr.removeFX( mWeaponCamShake ); - - SAFE_DELETE( mWeaponCamShake ); - } + mCubeReflector.unregisterReflector(); } } @@ -3161,40 +3151,9 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream) { if ( imageData->lightType == ShapeBaseImageData::WeaponFireLight ) image.lightStart = Sim::getCurrentTime(); - - // HACK: Only works properly if you are in control - // of the one and only shapeBase object in the scene - // which fires an image that uses camera shake. - if ( imageData->shakeCamera ) - { - if ( !mWeaponCamShake ) - { - mWeaponCamShake = new CameraShake(); - mWeaponCamShake->remoteControlled = true; - } - - mWeaponCamShake->init(); - mWeaponCamShake->setFrequency( imageData->camShakeFreq ); - mWeaponCamShake->setAmplitude( imageData->camShakeAmp ); - - if ( !mWeaponCamShake->isAdded ) - { - gCamFXMgr.addFX( mWeaponCamShake ); - mWeaponCamShake->isAdded = true; - } - } } updateImageState(i,0); - - if ( !image.triggerDown && !image.altTriggerDown ) - { - if ( mWeaponCamShake && mWeaponCamShake->isAdded ) - { - gCamFXMgr.removeFX( mWeaponCamShake ); - mWeaponCamShake->isAdded = false; - } - } } else { diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index a46a41580..55499a8e7 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -324,7 +324,10 @@ struct ShapeBaseImageData: public GameBaseData { /// @{ bool shakeCamera; VectorF camShakeFreq; - VectorF camShakeAmp; + VectorF camShakeAmp; + F32 camShakeDuration; + F32 camShakeRadius; + F32 camShakeFalloff; /// @} /// Maximum number of sounds this image can play at a time. @@ -903,9 +906,6 @@ protected: bool mFlipFadeVal; - /// Camera shake caused by weapon fire. - CameraShake *mWeaponCamShake; - public: /// @name Collision Notification @@ -1101,6 +1101,7 @@ protected: virtual void onImageAnimThreadChange(U32 imageSlot, S32 imageShapeIndex, ShapeBaseImageData::StateData* lastState, const char* anim, F32 pos, F32 timeScale, bool reset=false); virtual void onImageAnimThreadUpdate(U32 imageSlot, S32 imageShapeIndex, F32 dt); virtual void ejectShellCasing( U32 imageSlot ); + virtual void shakeCamera( U32 imageSlot ); virtual void updateDamageLevel(); virtual void updateDamageState(); virtual void onImpact(SceneObject* obj, VectorF vec); diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index 548984ca8..e9859e3de 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -44,6 +44,7 @@ #include "sfx/sfxTypes.h" #include "scene/sceneManager.h" #include "core/stream/fileStream.h" +#include "T3D/fx/cameraFXMgr.h" //---------------------------------------------------------------------------- @@ -297,6 +298,9 @@ ShapeBaseImageData::ShapeBaseImageData() shakeCamera = false; camShakeFreq = Point3F::Zero; camShakeAmp = Point3F::Zero; + camShakeDuration = 1.5f; + camShakeRadius = 3.0f; + camShakeFalloff = 10.0f; } ShapeBaseImageData::~ShapeBaseImageData() @@ -739,10 +743,7 @@ void ShapeBaseImageData::initPersistFields() "@see lightType"); addField( "shakeCamera", TypeBool, Offset(shakeCamera, ShapeBaseImageData), - "@brief Flag indicating whether the camera should shake when this Image fires.\n\n" - "@note Camera shake only works properly if the player is in control of " - "the one and only shapeBase object in the scene which fires an Image that " - "uses camera shake." ); + "@brief Flag indicating whether the camera should shake when this Image fires.\n\n" ); addField( "camShakeFreq", TypePoint3F, Offset(camShakeFreq, ShapeBaseImageData), "@brief Frequency of the camera shaking effect.\n\n" @@ -752,6 +753,16 @@ void ShapeBaseImageData::initPersistFields() "@brief Amplitude of the camera shaking effect.\n\n" "@see shakeCamera" ); + addField( "camShakeDuration", TypeF32, Offset(camShakeDuration, ShapeBaseImageData), + "Duration (in seconds) to shake the camera." ); + + addField( "camShakeRadius", TypeF32, Offset(camShakeRadius, ShapeBaseImageData), + "Radial distance that a camera's position must be within relative to the " + "center of the explosion to be shaken." ); + + addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ShapeBaseImageData), + "Falloff value for the camera shake." ); + addField( "casing", TYPEID< DebrisData >(), Offset(casing, ShapeBaseImageData), "@brief DebrisData datablock to use for ejected casings.\n\n" "@see stateEjectShell" ); @@ -1028,6 +1039,9 @@ void ShapeBaseImageData::packData(BitStream* stream) { mathWrite( *stream, camShakeFreq ); mathWrite( *stream, camShakeAmp ); + stream->write( camShakeDuration ); + stream->write( camShakeRadius ); + stream->write( camShakeFalloff ); } mathWrite( *stream, shellExitDir ); @@ -1208,7 +1222,10 @@ void ShapeBaseImageData::unpackData(BitStream* stream) if ( shakeCamera ) { mathRead( *stream, &camShakeFreq ); - mathRead( *stream, &camShakeAmp ); + mathRead( *stream, &camShakeAmp ); + stream->read( &camShakeDuration ); + stream->read( &camShakeRadius ); + stream->read( &camShakeFalloff ); } mathRead( *stream, &shellExitDir ); @@ -2596,6 +2613,10 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force) ejectShellCasing( imageSlot ); } + // Shake camera on client. + if (isGhost() && nextStateData.fire && image.dataBlock->shakeCamera) { + shakeCamera( imageSlot ); + } // Server must animate the shape if it is a firestate... if (isServerObject() && (image.dataBlock->state[newState].fire || image.dataBlock->state[newState].altFire)) @@ -3342,3 +3363,57 @@ void ShapeBase::ejectShellCasing( U32 imageSlot ) casing->init( shellPos, shellVel ); } + +void ShapeBase::shakeCamera( U32 imageSlot ) +{ + MountedImage& image = mMountedImageList[imageSlot]; + ShapeBaseImageData* imageData = image.dataBlock; + + if (!imageData->shakeCamera) + return; + + // Warning: this logic was duplicated from Explosion. + + // first check if explosion is near camera + GameConnection* connection = GameConnection::getConnectionToServer(); + ShapeBase *obj = dynamic_cast(connection->getControlObject()); + + bool applyShake = true; + + if (obj) + { + ShapeBase* cObj = obj; + while ((cObj = cObj->getControlObject()) != 0) + { + if (cObj->useObjsEyePoint()) + { + applyShake = false; + break; + } + } + } + + if (applyShake && obj) + { + VectorF diff; + getMuzzlePoint(imageSlot, &diff); + diff = obj->getPosition() - diff; + F32 dist = diff.len(); + if (dist < imageData->camShakeRadius) + { + CameraShake *camShake = new CameraShake; + camShake->setDuration(imageData->camShakeDuration); + camShake->setFrequency(imageData->camShakeFreq); + + F32 falloff = dist / imageData->camShakeRadius; + falloff = 1.0f + falloff * 10.0f; + falloff = 1.0f / (falloff * falloff); + + VectorF shakeAmp = imageData->camShakeAmp * falloff; + camShake->setAmplitude(shakeAmp); + camShake->setFalloff(imageData->camShakeFalloff); + camShake->init(); + gCamFXMgr.addFX(camShake); + } + } +} \ No newline at end of file diff --git a/Engine/source/app/version.h b/Engine/source/app/version.h index 9f68b2cbc..4a03f5ddc 100644 --- a/Engine/source/app/version.h +++ b/Engine/source/app/version.h @@ -41,10 +41,10 @@ /// code version, the game name, and which type of game it is (TGB, TGE, TGEA, etc.). /// /// Version number is major * 1000 + minor * 100 + revision * 10. -#define TORQUE_GAME_ENGINE 3620 +#define TORQUE_GAME_ENGINE 3630 /// Human readable engine version string. -#define TORQUE_GAME_ENGINE_VERSION_STRING "3.6.2" +#define TORQUE_GAME_ENGINE_VERSION_STRING "3.6.3" /// Gets the engine version number. The version number is specified as a global in version.cc U32 getVersionNumber(); diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index 629542531..e38aa1e9d 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -1599,8 +1599,7 @@ void SimObject::unlinkNamespaces() // Handle object name. - StringTableEntry objectName = getName(); - if( objectName && objectName[ 0 ] ) + if (mNameSpace && mNameSpace->mClassRep == NULL) mNameSpace->decRefCountToParent(); mNameSpace = NULL; diff --git a/Engine/source/environment/meshRoad.cpp b/Engine/source/environment/meshRoad.cpp index 6a5e3fbd1..453250568 100644 --- a/Engine/source/environment/meshRoad.cpp +++ b/Engine/source/environment/meshRoad.cpp @@ -49,6 +49,7 @@ #include "collision/concretePolyList.h" #include "T3D/physics/physicsPlugin.h" #include "T3D/physics/physicsBody.h" +#include "T3D/physics/physicsCollision.h" #include "environment/nodeListManager.h" #define MIN_METERS_PER_SEGMENT 1.0f @@ -1722,6 +1723,8 @@ void MeshRoad::_generateSlices() void MeshRoad::_generateSegments() { + SAFE_DELETE( mPhysicsRep ); + mSegments.clear(); for ( U32 i = 0; i < mSlices.size() - 1; i++ ) @@ -1736,8 +1739,22 @@ void MeshRoad::_generateSegments() if ( PHYSICSMGR ) { - SAFE_DELETE( mPhysicsRep ); - //mPhysicsRep = PHYSICSMGR->createBody(); + ConcretePolyList polylist; + if ( buildPolyList( PLC_Collision, &polylist, getWorldBox(), getWorldSphere() ) ) + { + polylist.triangulate(); + + PhysicsCollision *colShape = PHYSICSMGR->createCollision(); + colShape->addTriangleMesh( polylist.mVertexList.address(), + polylist.mVertexList.size(), + polylist.mIndexList.address(), + polylist.mIndexList.size() / 3, + MatrixF::Identity ); + + PhysicsWorld *world = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" ); + mPhysicsRep = PHYSICSMGR->createBody(); + mPhysicsRep->init( colShape, 0, 0, this, world ); + } } } diff --git a/Engine/source/environment/scatterSky.cpp b/Engine/source/environment/scatterSky.cpp index ed5f8d3ad..a9d187c89 100644 --- a/Engine/source/environment/scatterSky.cpp +++ b/Engine/source/environment/scatterSky.cpp @@ -658,6 +658,11 @@ void ScatterSky::prepRenderImage( SceneRenderState *state ) mFlareState.lightMat.identity(); mFlareState.lightMat.setPosition( lightPos ); + F32 dist = ( lightPos - state->getCameraPosition( ) ).len( ); + F32 coronaScale = 0.5f; + F32 screenRadius = GFX->getViewport( ).extent.y * coronaScale * 0.5f; + mFlareState.worldRadius = screenRadius * dist / state->getWorldToScreenScale( ).y; + mFlareData->prepRender( state, &mFlareState ); } diff --git a/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp b/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp index 99e664652..8d36776ca 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp @@ -130,6 +130,7 @@ GFXD3D9OcclusionQuery::OcclusionQueryStatus GFXD3D9OcclusionQuery::getStatus( bo //If we're stalled out, proceed with worst-case scenario -BJR if(GFX->mFrameTime->getElapsedMs()>4) { + this->begin(); this->end(); return NotOccluded; } diff --git a/Engine/source/gfx/gfxOcclusionQuery.h b/Engine/source/gfx/gfxOcclusionQuery.h index 9bf87c46d..ac6b0bf07 100644 --- a/Engine/source/gfx/gfxOcclusionQuery.h +++ b/Engine/source/gfx/gfxOcclusionQuery.h @@ -82,4 +82,71 @@ public: virtual const String describeSelf() const = 0; }; +/// Handle for GFXOcclusionQuery than store last valid state +class GFXOcclusionQueryHandle +{ +public: + + GFXOcclusionQueryHandle() + : mLastStatus(GFXOcclusionQuery::Unset), mLastData(0), mQuery(NULL), mWaiting(false) + {} + + ~GFXOcclusionQueryHandle() + { + SAFE_DELETE(mQuery); + } + + bool getLastStatus( bool block, GFXOcclusionQuery::OcclusionQueryStatus *statusPtr = NULL, U32 *data = NULL ); + GFXOcclusionQuery* getQuery() const { return mQuery; } + + void clearLastStatus() + { + mLastStatus = GFXOcclusionQuery::Unset; + mLastData = 0; + mWaiting = false; + + if( !mQuery ) + return; + + mQuery->begin(); + mQuery->end(); + } + + bool isWaiting() const { return mWaiting; } +protected: + GFXOcclusionQuery::OcclusionQueryStatus mLastStatus; + U32 mLastData; + bool mWaiting; + GFXOcclusionQuery *mQuery; +}; + +inline bool GFXOcclusionQueryHandle::getLastStatus( bool block, GFXOcclusionQuery::OcclusionQueryStatus *statusPtr, U32 *data ) +{ + if( !mQuery ) + mQuery = GFX->createOcclusionQuery(); + + GFXOcclusionQuery::OcclusionQueryStatus status = mQuery->getStatus( block, data ); + + if( status == GFXOcclusionQuery::Waiting ) + { + mWaiting = true; + if( statusPtr ) + *statusPtr = mLastStatus; + if( data ) + *data = mLastData; + + return true; + } + + if( statusPtr ) + *statusPtr = status; + + mWaiting = false; + mLastStatus = status; + mLastData = *data; + + return true; +} + + #endif // _GFXOCCLUSIONQUERY_H_ \ No newline at end of file diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.cpp b/Engine/source/gui/controls/guiTreeViewCtrl.cpp index 7f36a5903..191160372 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.cpp +++ b/Engine/source/gui/controls/guiTreeViewCtrl.cpp @@ -1785,6 +1785,8 @@ bool GuiTreeViewCtrl::onWake() // make sure it's big enough for both bitmap AND font... mItemHeight = getMax((S32)mFont->getHeight(), (S32)mProfile->mBitmapArrayRects[0].extent.y); } + + mFlags.set(RebuildVisible); return true; } diff --git a/Engine/source/lighting/common/projectedShadow.cpp b/Engine/source/lighting/common/projectedShadow.cpp index 8918ddf5a..1ad88cd10 100644 --- a/Engine/source/lighting/common/projectedShadow.cpp +++ b/Engine/source/lighting/common/projectedShadow.cpp @@ -230,6 +230,9 @@ bool ProjectedShadow::_updateDecal( const SceneRenderState *state ) lightCount++; } + if (mShapeBase) + fade *= mShapeBase->getFadeVal(); + lightDir.normalize(); // No light... no shadow. diff --git a/Engine/source/materials/matInstance.cpp b/Engine/source/materials/matInstance.cpp index a61b75bf7..1a894f1a5 100644 --- a/Engine/source/materials/matInstance.cpp +++ b/Engine/source/materials/matInstance.cpp @@ -290,6 +290,12 @@ bool MatInstance::init( const FeatureSet &features, //---------------------------------------------------------------------------- bool MatInstance::reInit() { + if (!mVertexFormat) + { + mIsValid = false; + return mIsValid; + } + SAFE_DELETE(mProcessedMaterial); deleteAllHooks(); mIsValid = processMaterial(); diff --git a/Engine/source/materials/processedMaterial.h b/Engine/source/materials/processedMaterial.h index b72422cf9..97b267466 100644 --- a/Engine/source/materials/processedMaterial.h +++ b/Engine/source/materials/processedMaterial.h @@ -73,7 +73,7 @@ public: /// The cubemap to use when the texture type is /// set to Material::Cube. /// @see mTexType - GFXCubemap *mCubeMap; + GFXCubemapHandle mCubeMap; U32 mNumTex; diff --git a/Engine/source/math/mPlane.h b/Engine/source/math/mPlane.h index cb83788e1..a67d5c60b 100644 --- a/Engine/source/math/mPlane.h +++ b/Engine/source/math/mPlane.h @@ -383,9 +383,10 @@ inline PlaneF::Side PlaneF::whichSide( const OrientedBox3F& obb ) const // Project the box onto the line defined by the plane center and normal. // See "3D Game Engine Design" chapter 4.3.2. - const F32 r = obb.getHalfExtents().x * mFabs( mDot( obb.getAxis( 0 ), *this ) ) + - obb.getHalfExtents().y * mFabs( mDot( obb.getAxis( 1 ), *this ) ) + - obb.getHalfExtents().z * mFabs( mDot( obb.getAxis( 2 ), *this ) ); + Point3F mObbHalf = obb.getHalfExtents(); + const F32 r = mObbHalf.x * mFabs( mDot( obb.getAxis( 0 ), *this ) ) + + mObbHalf.y * mFabs( mDot( obb.getAxis( 1 ), *this ) ) + + mObbHalf.z * mFabs( mDot( obb.getAxis( 2 ), *this ) ); const F32 dist = distToPlane( obb.getCenter() ); if( dist > r ) diff --git a/Engine/source/math/mPlaneSet.h b/Engine/source/math/mPlaneSet.h index abeebd4dc..8d0a919bb 100644 --- a/Engine/source/math/mPlaneSet.h +++ b/Engine/source/math/mPlaneSet.h @@ -458,7 +458,7 @@ U32 PlaneSet< T >::clipPolygon( const Point3F* inVertices, U32 inNumVertices, Po // to indicate we haven't clipped anything. if( !numClippedPolygonVertices ) - return false; + return 0; // On first iteration, replace the inVertices with the // outVertices buffer. diff --git a/Engine/source/platform/nativeDialogs/msgBox.h b/Engine/source/platform/nativeDialogs/msgBox.h index 9c210a417..06c5e27c2 100644 --- a/Engine/source/platform/nativeDialogs/msgBox.h +++ b/Engine/source/platform/nativeDialogs/msgBox.h @@ -32,7 +32,7 @@ enum MBButtons { - MBOk, + MBOk = 0, MBOkCancel, MBRetryCancel, MBSaveDontSave, @@ -41,7 +41,7 @@ enum MBButtons enum MBIcons { - MIWarning, + MIWarning = 0, MIInformation, MIQuestion, MIStop, diff --git a/Engine/source/shaderGen/HLSL/depthHLSL.cpp b/Engine/source/shaderGen/HLSL/depthHLSL.cpp index 9f5726a51..ecb23d676 100644 --- a/Engine/source/shaderGen/HLSL/depthHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/depthHLSL.cpp @@ -25,7 +25,7 @@ #include "materials/materialFeatureTypes.h" #include "materials/materialFeatureData.h" - +#include "terrain/terrFeatureTypes.h" void EyeSpaceDepthOutHLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) @@ -85,7 +85,12 @@ void EyeSpaceDepthOutHLSL::processPix( Vector &componentList, LangElement *depthOutDecl = new DecOp( depthOut ); meta->addStatement( new GenOp( "#ifndef CUBE_SHADOW_MAP\r\n" ) ); - meta->addStatement( new GenOp( " @ = dot(@, (@.xyz / @.w));\r\n", depthOutDecl, vEye, wsEyeVec, wsEyeVec ) ); + + if (fd.features.hasFeature(MFT_TerrainBaseMap)) + meta->addStatement(new GenOp(" @ =min(0.9999, dot(@, (@.xyz / @.w)));\r\n", depthOutDecl, vEye, wsEyeVec, wsEyeVec)); + else + meta->addStatement(new GenOp(" @ = dot(@, (@.xyz / @.w));\r\n", depthOutDecl, vEye, wsEyeVec, wsEyeVec)); + meta->addStatement( new GenOp( "#else\r\n" ) ); Var *farDist = (Var*)Var::find( "oneOverFarplane" ); diff --git a/README.md b/README.md index 5aed4b20a..1ef223d89 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Torque 3D v3.6.2 +Torque 3D v3.6.3 ================ MIT Licensed Open Source version of [Torque 3D](http://www.garagegames.com/products/torque-3d) from [GarageGames](http://www.garagegames.com) @@ -23,7 +23,7 @@ In addition to GitHub we also have a couple of pre-packaged files for you to dow * [Torque 3D 3.6 Full template](http://mit.garagegames.com/Torque3D-3-6-1-FullTemplate.zip), which contains precompiled binaries. * [Complete Torque 3D 3.6 zip package](http://mit.garagegames.com/Torque3D-3-6-1.zip) containing the contents of this repository. -* [Windows binaries for 3.6.2](https://github.com/GarageGames/Torque3D/releases/tag/v3.6.2) which you can drop into your existing script projects. +* [Windows binaries for 3.6.3](https://github.com/GarageGames/Torque3D/releases/tag/v3.6.3) which you can drop into your existing script projects. * [Torque 3D Project Manager v2.1](http://mit.garagegames.com/T3DProjectManager-2-1.zip) on its own for use in your T3D forks. If you're looking for an older release see the [Torque 3D Archive](https://github.com/GarageGames/Torque3D/wiki/Torque-3D-Archive) diff --git a/Templates/Full/game/art/datablocks/player.cs b/Templates/Full/game/art/datablocks/player.cs index 27933628c..e920b3cce 100644 --- a/Templates/Full/game/art/datablocks/player.cs +++ b/Templates/Full/game/art/datablocks/player.cs @@ -482,7 +482,7 @@ datablock DebrisData( PlayerDebris ) datablock PlayerData(DefaultPlayerData) { renderFirstPerson = false; - + firstPersonShadows = true; computeCRC = false; // Third person shape diff --git a/Templates/Full/game/art/datablocks/weapons/Ryder.cs b/Templates/Full/game/art/datablocks/weapons/Ryder.cs index a94bfa8d6..7e0436aa0 100644 --- a/Templates/Full/game/art/datablocks/weapons/Ryder.cs +++ b/Templates/Full/game/art/datablocks/weapons/Ryder.cs @@ -192,9 +192,9 @@ datablock ShapeBaseImageData(RyderWeaponImage) lightBrightness = 2; // Shake camera while firing. - shakeCamera = false; - camShakeFreq = "0 0 0"; - camShakeAmp = "0 0 0"; + shakeCamera = "1"; + camShakeFreq = "10 10 10"; + camShakeAmp = "5 5 5"; // Images have a state system which controls how the animations // are run, which sounds are played, script callbacks, etc. This @@ -361,4 +361,5 @@ datablock ShapeBaseImageData(RyderWeaponImage) stateSequenceTransitionOut[13] = true; stateAllowImageChange[13] = false; stateSequence[13] = "sprint"; + camShakeDuration = "0.2"; }; diff --git a/Templates/Full/game/scripts/server/aiPlayer.cs b/Templates/Full/game/scripts/server/aiPlayer.cs index b9f5a66a6..70d7a2453 100644 --- a/Templates/Full/game/scripts/server/aiPlayer.cs +++ b/Templates/Full/game/scripts/server/aiPlayer.cs @@ -212,7 +212,10 @@ function AIPlayer::singleShot(%this) // The shooting delay is used to pulse the trigger %this.setImageTrigger(0, true); %this.setImageTrigger(0, false); - %this.trigger = %this.schedule(%this.shootingDelay, singleShot); + %delay = %this.getDataBlock().shootingDelay; + if (%delay $= "") + %delay = 1000; + %this.trigger = %this.schedule(%delay, singleShot); } //-----------------------------------------------------------------------------