Browse Source

Code cleanup.
Fixed lit base pass optimization working only for the first subgeometry of an object.
Calculate per-subgeometry distances in UpdateDistance() for StaticModel & AnimatedModel.

Lasse Öörni 14 years ago
parent
commit
9d077e78a8

+ 9 - 3
Engine/Graphics/AnimatedModel.cpp

@@ -205,7 +205,12 @@ void AnimatedModel::Update(const FrameInfo& frame)
 
 void AnimatedModel::UpdateDistance(const FrameInfo& frame)
 {
-    distance_ = frame.camera_->GetDistance(GetWorldPosition());
+    const Matrix3x4& worldTransform = GetWorldTransform();
+    distance_ = frame.camera_->GetDistance(worldTransform.Translation());
+    
+    // Note: per-geometry distances do not take skinning into account
+    for (unsigned i = 0; i < geometryCenters_.Size(); ++i)
+        geometryDistances_[i] = frame.camera_->GetDistance(worldTransform * geometryCenters_[i]);
     
     float scale = GetWorldBoundingBox().Size().DotProduct(DOT_SCALE);
     float newLodDistance = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
@@ -238,9 +243,9 @@ void AnimatedModel::UpdateGeometry(const FrameInfo& frame)
         UpdateSkinning();
 }
 
-void AnimatedModel::GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch)
+void AnimatedModel::GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex)
 {
-    batch.distance_ = frame.camera_->GetDistance(GetWorldTransform() * geometryCenters_[batchIndex]);
+    batch.distance_ = geometryDistances_[batchIndex];
     batch.geometry_ = geometries_[batchIndex][lodLevels_[batchIndex]];
     batch.geometryType_ = GEOM_SKINNED;
     batch.worldTransform_ = &GetWorldTransform();
@@ -288,6 +293,7 @@ void AnimatedModel::SetModel(Model* model, bool createBones)
     for (unsigned i = 0; i < geometries.Size(); ++i)
         geometries_[i] = geometries[i];
     geometryCenters_ = model->GetGeometryCenters();
+    geometryDistances_.Resize(geometryCenters_.Size());
     
     // Copy geometry bone mappings
     const Vector<PODVector<unsigned> >& geometryBoneMappings = model->GetGeometryBoneMappings();

+ 2 - 2
Engine/Graphics/AnimatedModel.h

@@ -56,8 +56,8 @@ public:
     virtual void UpdateDistance(const FrameInfo& frame);
     /// Prepare geometry for rendering.
     virtual void UpdateGeometry(const FrameInfo& frame);
-    /// Return rendering batch with distance, geometry, material and world transform filled.
-    virtual void GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch);
+    /// Fill rendering batch with distance, geometry, material and world transform.
+    virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex);
     /// Add debug geometry to the debug graphics.
     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     

+ 21 - 21
Engine/Graphics/Batch.cpp

@@ -71,7 +71,7 @@ void Batch::CalculateSortKey()
     unsigned pass = (*((unsigned*)&pass_) / sizeof(Pass)) & 0xffff;
     unsigned material = (*((unsigned*)&material_) / sizeof(Material)) & 0xffff;
     unsigned geometry = (*((unsigned*)&geometry_) / sizeof(Geometry)) & 0xffff;
-    if (hasPriority_)
+    if (isBase_)
         lightQueue |= 0x8000;
     sortKey_ = (((unsigned long long)lightQueue) << 48) | (((unsigned long long)pass) << 32) |
         (((unsigned long long)material) << 16) | geometry;
@@ -200,7 +200,7 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, bool setModelTransfo
         
         if (graphics->NeedParameterUpdate(VSP_LIGHTVECROT, light))
         {
-            Matrix3x4 lightVecRot(Vector3::ZERO, light->GetWorldRotation(), Vector3::UNITY);
+            Matrix3x4 lightVecRot(Vector3::ZERO, light->GetWorldRotation(), Vector3::ONE);
             graphics->SetShaderParameter(VSP_LIGHTVECROT, lightVecRot);
         }
         
@@ -585,9 +585,9 @@ void BatchGroup::Draw(Graphics* graphics, Renderer* renderer) const
 void BatchQueue::Clear()
 {
     batches_.Clear();
-    sortedPriorityBatches_.Clear();
+    sortedBaseBatches_.Clear();
     sortedBatches_.Clear();
-    priorityBatchGroups_.Clear();
+    baseBatchGroups_.Clear();
     batchGroups_.Clear();
 }
 
@@ -605,7 +605,7 @@ void BatchQueue::AddBatch(const Batch& batch, bool instancing)
         key.material_ = batch.material_;
         key.geometry_ = batch.geometry_;
         
-        Map<BatchGroupKey, BatchGroup>* groups = batch.hasPriority_ ? &priorityBatchGroups_ : &batchGroups_;
+        Map<BatchGroupKey, BatchGroup>* groups = batch.isBase_ ? &baseBatchGroups_ : &batchGroups_;
         
         Map<BatchGroupKey, BatchGroup>::Iterator i = groups->Find(key);
         if (i == groups->End())
@@ -631,7 +631,7 @@ void BatchQueue::AddBatch(const Batch& batch, bool instancing)
 
 void BatchQueue::SortBackToFront()
 {
-    sortedPriorityBatches_.Clear();
+    sortedBaseBatches_.Clear();
     sortedBatches_.Resize(batches_.Size());
     
     for (unsigned i = 0; i < batches_.Size(); ++i)
@@ -640,12 +640,12 @@ void BatchQueue::SortBackToFront()
     Sort(sortedBatches_.Begin(), sortedBatches_.End(), CompareBatchesBackToFront);
     
     // Do not actually sort batch groups, just list them
-    sortedPriorityBatchGroups_.Resize(priorityBatchGroups_.Size());
+    sortedBaseBatchGroups_.Resize(baseBatchGroups_.Size());
     sortedBatchGroups_.Resize(batchGroups_.Size());
     
     unsigned index = 0;
-    for (Map<BatchGroupKey, BatchGroup>::Iterator i = priorityBatchGroups_.Begin(); i != priorityBatchGroups_.End(); ++i)
-        sortedPriorityBatchGroups_[index++] = &i->second_;
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
+        sortedBaseBatchGroups_[index++] = &i->second_;
     index = 0;
     for (Map<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
         sortedBatchGroups_[index++] = &i->second_;
@@ -653,46 +653,46 @@ void BatchQueue::SortBackToFront()
 
 void BatchQueue::SortFrontToBack()
 {
-    sortedPriorityBatches_.Clear();
+    sortedBaseBatches_.Clear();
     sortedBatches_.Clear();
     
-    // Must explicitly divide into priority batches and non-priority, so that priorities do not get mixed up between
+    // Must explicitly divide into base and non-base batches, so that priorities do not get mixed up between
     // instanced and non-instanced batches
     for (unsigned i = 0; i < batches_.Size(); ++i)
     {
-        if (batches_[i].hasPriority_)
-            sortedPriorityBatches_.Push(&batches_[i]);
+        if (batches_[i].isBase_)
+            sortedBaseBatches_.Push(&batches_[i]);
         else
             sortedBatches_.Push(&batches_[i]);
     }
     
-    Sort(sortedPriorityBatches_.Begin(), sortedPriorityBatches_.End(), CompareBatchesFrontToBack);
+    Sort(sortedBaseBatches_.Begin(), sortedBaseBatches_.End(), CompareBatchesFrontToBack);
     Sort(sortedBatches_.Begin(), sortedBatches_.End(), CompareBatchesFrontToBack);
     
     // Sort each group front to back
-    for (Map<BatchGroupKey, BatchGroup>::Iterator i = priorityBatchGroups_.Begin(); i != priorityBatchGroups_.End(); ++i)
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
         Sort(i->second_.instances_.Begin(), i->second_.instances_.End(), CompareInstancesFrontToBack);
     for (Map<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
         Sort(i->second_.instances_.Begin(), i->second_.instances_.End(), CompareInstancesFrontToBack);
     
     // Now sort batch groups by the distance of the first batch
-    sortedPriorityBatchGroups_.Resize(priorityBatchGroups_.Size());
+    sortedBaseBatchGroups_.Resize(baseBatchGroups_.Size());
     sortedBatchGroups_.Resize(batchGroups_.Size());
     
     unsigned index = 0;
-    for (Map<BatchGroupKey, BatchGroup>::Iterator i = priorityBatchGroups_.Begin(); i != priorityBatchGroups_.End(); ++i)
-        sortedPriorityBatchGroups_[index++] = &i->second_;
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
+        sortedBaseBatchGroups_[index++] = &i->second_;
     index = 0;
     for (Map<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
         sortedBatchGroups_[index++] = &i->second_;
     
-    Sort(sortedPriorityBatchGroups_.Begin(), sortedPriorityBatchGroups_.End(), CompareBatchGroupsFrontToBack);
+    Sort(sortedBaseBatchGroups_.Begin(), sortedBaseBatchGroups_.End(), CompareBatchGroupsFrontToBack);
     Sort(sortedBatchGroups_.Begin(), sortedBatchGroups_.End(), CompareBatchGroupsFrontToBack);
 }
 
 void BatchQueue::SetTransforms(Renderer* renderer, void* lockedData, unsigned& freeIndex)
 {
-    for (Map<BatchGroupKey, BatchGroup>::Iterator i = priorityBatchGroups_.Begin(); i != priorityBatchGroups_.End(); ++i)
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
         i->second_.SetTransforms(renderer, lockedData, freeIndex);
     for (Map<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
         i->second_.SetTransforms(renderer, lockedData, freeIndex);
@@ -706,7 +706,7 @@ unsigned BatchQueue::GetNumInstances(Renderer* renderer) const
     
     // This is for the purpose of calculating how much space is needed in the instancing buffer. Do not add instance counts
     // that are below the minimum threshold for instancing
-    for (Map<BatchGroupKey, BatchGroup>::ConstIterator i = priorityBatchGroups_.Begin(); i != priorityBatchGroups_.End(); ++i)
+    for (Map<BatchGroupKey, BatchGroup>::ConstIterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
     {
         unsigned instances = i->second_.instances_.Size();
         if (instances >= minGroupSize && i->second_.geometry_->GetIndexCount() <= maxIndexCount)

+ 13 - 13
Engine/Graphics/Batch.h

@@ -57,11 +57,11 @@ struct Batch
         shaderDataSize_(0),
         geometryType_(GEOM_STATIC),
         overrideView_(false),
-        hasPriority_(false)
+        isBase_(false)
     {
     }
     
-    /// Calculate sort key, which consists of priority flag, light, pass and geometry.
+    /// Calculate state sorting key, which consists of base pass flag, light, pass and geometry.
     void CalculateSortKey();
     /// Prepare for rendering.
     void Prepare(Graphics* graphics, Renderer* renderer, bool setModelTransform = true) const;
@@ -100,8 +100,8 @@ struct Batch
     unsigned char vertexShaderIndex_;
     /// Override view transform flag.
     bool overrideView_;
-    /// Priority flag.
-    bool hasPriority_;
+    /// Base batch flag. This tells to draw the object fully without light optimizations.
+    bool isBase_;
 };
 
 /// Data for one geometry instance.
@@ -162,10 +162,10 @@ struct BatchGroup
     ShaderVariation* vertexShader_;
     /// Pixel shader.
     ShaderVariation* pixelShader_;
-    /// Vertex shader index.
-    unsigned char vertexShaderIndex_;
     /// Instance stream start index, or M_MAX_UNSIGNED if transforms not pre-set.
     unsigned startIndex_;
+    /// Vertex shader index.
+    unsigned char vertexShaderIndex_;
 };
 
 /// Instanced draw call key.
@@ -254,19 +254,19 @@ public:
     /// Return the combined amount of instances.
     unsigned GetNumInstances(Renderer* renderer) const;
     /// Return whether the batch group is empty.
-    bool IsEmpty() const { return batches_.Empty() && priorityBatchGroups_.Empty() && batchGroups_.Empty(); }
+    bool IsEmpty() const { return batches_.Empty() && baseBatchGroups_.Empty() && batchGroups_.Empty(); }
     /// Unsorted non-instanced draw calls.
     PODVector<Batch> batches_;
-    /// Instanced draw calls with priority flag.
-    Map<BatchGroupKey, BatchGroup> priorityBatchGroups_;
+    /// Instanced draw calls with base flag.
+    Map<BatchGroupKey, BatchGroup> baseBatchGroups_;
     /// Instanced draw calls.
     Map<BatchGroupKey, BatchGroup> batchGroups_;
-    /// Sorted non-instanced draw calls with priority flag.
-    PODVector<Batch*> sortedPriorityBatches_;
+    /// Sorted non-instanced draw calls with base flag.
+    PODVector<Batch*> sortedBaseBatches_;
     /// Sorted non-instanced draw calls.
     PODVector<Batch*> sortedBatches_;
-    /// Sorted instanced draw calls with priority flag.
-    PODVector<BatchGroup*> sortedPriorityBatchGroups_;
+    /// Sorted instanced draw calls with base flag.
+    PODVector<BatchGroup*> sortedBaseBatchGroups_;
     /// Sorted instanced draw calls.
     PODVector<BatchGroup*> sortedBatchGroups_;
 };

+ 6 - 6
Engine/Graphics/BillboardSet.cpp

@@ -143,9 +143,9 @@ unsigned BillboardSet::GetNumBatches()
     return 1;
 }
 
-void BillboardSet::GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch)
+void BillboardSet::GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex)
 {
-    batch.distance_ = frame.camera_->GetDistance(GetWorldPosition());
+    batch.distance_ = distance_;
     batch.geometry_ = geometry_;
     batch.geometryType_ = GEOM_BILLBOARD;
     batch.worldTransform_ = &GetWorldTransform();
@@ -167,7 +167,7 @@ void BillboardSet::SetNumBillboards(unsigned num)
     for (unsigned i = oldNum; i < num; ++i)
     {
         billboards_[i].position_ = Vector3::ZERO;
-        billboards_[i].size_ = Vector2::UNITY;
+        billboards_[i].size_ = Vector2::ONE;
         billboards_[i].uv_ = Rect::POSITIVE;
         billboards_[i].color_ = Color(1.0f, 1.0f, 1.0f);
         billboards_[i].rotation_ = 0.0f;
@@ -303,7 +303,7 @@ void BillboardSet::OnWorldBoundingBoxUpdate()
     unsigned enabledBillboards = 0;
     const Matrix3x4& worldTransform = GetWorldTransform();
     Matrix3x4 billboardTransform = relative_ ? worldTransform : Matrix3x4::IDENTITY;
-    Vector3 billboardScale = scaled_ ? worldTransform.Scale() : Vector3::UNITY;
+    Vector3 billboardScale = scaled_ ? worldTransform.Scale() : Vector3::ONE;
     
     for (unsigned i = 0; i < billboards_.Size(); ++i)
     {
@@ -312,7 +312,7 @@ void BillboardSet::OnWorldBoundingBoxUpdate()
         
         float size = INV_SQRT_TWO * (billboards_[i].size_.x_ * billboardScale.x_ + billboards_[i].size_.y_ * billboardScale.y_);
         Vector3 center = billboardTransform * billboards_[i].position_;
-        Vector3 edge = Vector3::UNITY * size;
+        Vector3 edge = Vector3::ONE * size;
         worldBoundingBox_.Merge(BoundingBox(center - edge, center + edge));
         
         ++enabledBillboards;
@@ -381,7 +381,7 @@ void BillboardSet::UpdateVertexBuffer(const FrameInfo& frame)
     unsigned enabledBillboards = 0;
     const Matrix3x4& worldTransform = GetWorldTransform();
     Matrix3x4 billboardTransform = relative_ ? worldTransform : Matrix3x4::IDENTITY;
-    Vector3 billboardScale = scaled_ ? worldTransform.Scale() : Vector3::UNITY;
+    Vector3 billboardScale = scaled_ ? worldTransform.Scale() : Vector3::ONE;
     
     // First check number of enabled billboards
     for (unsigned i = 0; i < numBillboards; ++i)

+ 2 - 2
Engine/Graphics/BillboardSet.h

@@ -69,8 +69,8 @@ public:
     virtual void UpdateGeometry(const FrameInfo& frame);
     /// Return number of batches.
     virtual unsigned GetNumBatches();
-    /// Return rendering batch with distance, geometry, material and world transform filled.
-    virtual void GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch);
+    /// Fill rendering batch with distance, geometry, material and world transform.
+    virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex);
     
     /// %Set material.
     void SetMaterial(Material* material);

+ 6 - 7
Engine/Graphics/Drawable.cpp

@@ -29,9 +29,8 @@
 #include "Octree.h"
 #include "OctreeQuery.h"
 #include "Scene.h"
-#include "Zone.h"
-
 #include "Sort.h"
+#include "Zone.h"
 
 #include "DebugNew.h"
 
@@ -49,16 +48,16 @@ Drawable::Drawable(Context* context) :
     lightMask_(DEFAULT_LIGHTMASK),
     zoneMask_(DEFAULT_ZONEMASK),
     maxLights_(0),
-    drawableFlags_(0),
-    visible_(true),
-    castShadows_(false),
-    occluder_(false),
     distance_(0.0f),
     lodDistance_(0.0f),
     sortValue_(0.0f),
     viewFrameNumber_(0),
     viewCamera_(0),
     firstLight_(0),
+    drawableFlags_(0),
+    visible_(true),
+    castShadows_(false),
+    occluder_(false),
     worldBoundingBoxDirty_(true),
     lodLevelsDirty_(true)
 {
@@ -234,7 +233,7 @@ void Drawable::LimitLights()
 
 void Drawable::SetBasePass(unsigned batchIndex)
 {
-    unsigned index = batchIndex << 5;
+    unsigned index = batchIndex >> 5;
     if (basePassFlags_.Size() <= index)
     {
         unsigned oldSize = basePassFlags_.Size();

+ 14 - 14
Engine/Graphics/Drawable.h

@@ -85,8 +85,8 @@ public:
     virtual void UpdateGeometry(const FrameInfo& frame) {}
     /// Return number of rendering batches.
     virtual unsigned GetNumBatches() { return 0; }
-    /// Return rendering batch with distance, geometry, material and world transform filled.
-    virtual void GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch) {}
+    /// Fill rendering batch with distance, geometry, material and world transform.
+    virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex) {}
     /// Draw to occlusion buffer.
     virtual bool DrawOcclusion(OcclusionBuffer* buffer) { return true; }
     /// Draw debug geometry.
@@ -195,10 +195,6 @@ protected:
     
     /// Octree octant.
     Octant* octant_;
-    /// Current zone.
-    WeakPtr<Zone> zone_;
-    /// Previous zone.
-    WeakPtr<Zone> lastZone_;
     /// World bounding box.
     BoundingBox worldBoundingBox_;
     /// Draw distance.
@@ -215,14 +211,6 @@ protected:
     unsigned zoneMask_;
     /// Maximum lights.
     unsigned maxLights_;
-    /// Drawable flags.
-    unsigned char drawableFlags_;
-    /// Visible flag.
-    bool visible_;
-    /// Shadowcaster flag.
-    bool castShadows_;
-    /// Occluder flag.
-    bool occluder_;
     /// Current distance to camera.
     float distance_;
     /// LOD scaled distance.
@@ -239,6 +227,18 @@ protected:
     PODVector<Light*> lights_;
     /// First light added this frame.
     Light* firstLight_;
+    /// Current zone.
+    WeakPtr<Zone> zone_;
+    /// Previous zone.
+    WeakPtr<Zone> lastZone_;
+    /// Drawable flags.
+    unsigned char drawableFlags_;
+    /// Visible flag.
+    bool visible_;
+    /// Shadowcaster flag.
+    bool castShadows_;
+    /// Occluder flag.
+    bool occluder_;
     /// Bounding box dirty flag.
     bool worldBoundingBoxDirty_;
     /// Lod levels dirty flag.

+ 1 - 1
Engine/Graphics/Material.cpp

@@ -89,7 +89,7 @@ Material::Material(Context* context) :
     // Setup often used default parameters
     SetShaderParameter("UOffset", Vector4(1.0f, 0.0f, 0.0f, 0.0f));
     SetShaderParameter("VOffset", Vector4(0.0f, 1.0f, 0.0f, 0.0f));
-    SetShaderParameter("MatDiffColor", Vector4::UNITY);
+    SetShaderParameter("MatDiffColor", Vector4::ONE);
     SetShaderParameter("MatEmissiveColor", Vector4::ZERO);
     SetShaderParameter("MatSpecProperties", Vector4::ZERO);
     

+ 2 - 2
Engine/Graphics/Octree.cpp

@@ -276,8 +276,8 @@ void Octree::RegisterObject(Context* context)
 {
     context->RegisterFactory<Octree>();
     
-    Vector3 defaultBoundsMin = Vector3::UNITY * DEFAULT_OCTREE_SIZE;
-    Vector3 defaultBoundsMax = -Vector3::UNITY * DEFAULT_OCTREE_SIZE;
+    Vector3 defaultBoundsMin = Vector3::ONE * DEFAULT_OCTREE_SIZE;
+    Vector3 defaultBoundsMax = -Vector3::ONE * DEFAULT_OCTREE_SIZE;
     
     ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Min", worldBoundingBox_.min_, defaultBoundsMin, AM_DEFAULT);
     ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Max", worldBoundingBox_.max_, defaultBoundsMax, AM_DEFAULT);

+ 1 - 1
Engine/Graphics/ParticleEmitter.cpp

@@ -142,7 +142,7 @@ void ParticleEmitter::Update(float timeStep)
     // Update existing particles
     Vector3 relativeConstantForce = GetWorldRotation().Inverse() * constanceForce_;
     // If billboards are not relative, apply scaling to the position update
-    Vector3 scaleVector = Vector3::UNITY;
+    Vector3 scaleVector = Vector3::ONE;
     if (scaled_ && !relative_)
         scaleVector = GetWorldScale();
     

+ 1 - 1
Engine/Graphics/Skeleton.h

@@ -44,7 +44,7 @@ struct Bone
         radius_(0.0f),
         initialPosition_(Vector3::ZERO),
         initialRotation_(Quaternion::IDENTITY),
-        initialScale_(Vector3::UNITY),
+        initialScale_(Vector3::ONE),
         animated_(true)
     {
     }

+ 2 - 2
Engine/Graphics/Skybox.cpp

@@ -55,10 +55,10 @@ void Skybox::UpdateDistance(const FrameInfo& frame)
     distance_ = 0.0f;
 }
 
-void Skybox::GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch)
+void Skybox::GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex)
 {
     // Follow only the camera rotation, not position
-    Matrix3x4 customView(Vector3::ZERO, frame.camera_->GetWorldRotation().Inverse(), Vector3::UNITY);
+    Matrix3x4 customView(Vector3::ZERO, frame.camera_->GetWorldRotation().Inverse(), Vector3::ONE);
     customWorldTransform_ = customView * GetWorldTransform();
     
     batch.distance_ = 0.0f;

+ 2 - 2
Engine/Graphics/Skybox.h

@@ -42,8 +42,8 @@ public:
     void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
     /// Calculate distance for rendering.
     virtual void UpdateDistance(const FrameInfo& frame);
-    /// Return rendering batch with distance, geometry, material and world transform filled.
-    virtual void GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch);
+    /// Fill rendering batch with distance, geometry, material and world transform.
+    virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex);
     
 protected:
     /// Recalculate the world-space bounding box.

+ 23 - 2
Engine/Graphics/StaticModel.cpp

@@ -39,6 +39,8 @@
 
 #include "DebugNew.h"
 
+static const Vector3 DOT_SCALE(1 / 3.0f, 1 / 3.0f, 1 / 3.0f);
+
 OBJECTTYPESTATIC(StaticModel);
 
 StaticModel::StaticModel(Context* context) :
@@ -142,6 +144,24 @@ void StaticModel::ProcessRayQuery(RayOctreeQuery& query, float initialDistance)
     }
 }
 
+void StaticModel::UpdateDistance(const FrameInfo& frame)
+{
+    const Matrix3x4& worldTransform = GetWorldTransform();
+    distance_ = frame.camera_->GetDistance(worldTransform.Translation());
+    
+    for (unsigned i = 0; i < geometryCenters_.Size(); ++i)
+        geometryDistances_[i] = frame.camera_->GetDistance(worldTransform * geometryCenters_[i]);
+    
+    float scale = GetWorldBoundingBox().Size().DotProduct(DOT_SCALE);
+    float newLodDistance = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
+    
+    if (newLodDistance != lodDistance_)
+    {
+        lodDistance_ = newLodDistance;
+        lodLevelsDirty_ = true;
+    }
+}
+
 void StaticModel::UpdateGeometry(const FrameInfo& frame)
 {
     if (lodLevelsDirty_)
@@ -153,9 +173,9 @@ unsigned StaticModel::GetNumBatches()
     return geometries_.Size();
 }
 
-void StaticModel::GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch)
+void StaticModel::GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex)
 {
-    batch.distance_ = frame.camera_->GetDistance(GetWorldTransform() * geometryCenters_[batchIndex]);
+    batch.distance_ = geometryDistances_[batchIndex];
     batch.geometry_ = geometries_[batchIndex][lodLevels_[batchIndex]];
     batch.worldTransform_ = &GetWorldTransform();
     batch.material_ = materials_[batchIndex];
@@ -233,6 +253,7 @@ void StaticModel::SetModel(Model* model)
     for (unsigned i = 0; i < geometries.Size(); ++i)
         geometries_[i] = geometries[i];
     geometryCenters_ = model->GetGeometryCenters();
+    geometryDistances_.Resize(geometryCenters_.Size());
     
     SetBoundingBox(model->GetBoundingBox());
     ResetLodLevels();

+ 6 - 2
Engine/Graphics/StaticModel.h

@@ -42,12 +42,14 @@ public:
     
     /// Process octree raycast.
     virtual void ProcessRayQuery(RayOctreeQuery& query, float initialDistance);
+    /// Calculate distance for rendering.
+    virtual void UpdateDistance(const FrameInfo& frame);
     /// Prepare geometry for rendering.
     virtual void UpdateGeometry(const FrameInfo& frame);
     /// Return number of batches.
     virtual unsigned GetNumBatches();
-    /// Return rendering batch with distance, geometry, material and world transform filled.
-    virtual void GetBatch(const FrameInfo& frame, unsigned batchIndex, Batch& batch);
+    /// Fill rendering batch with distance, geometry, material and world transform.
+    virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex);
     /// Draw to occlusion buffer.
     virtual bool DrawOcclusion(OcclusionBuffer* buffer);
     
@@ -100,6 +102,8 @@ protected:
     Vector<Vector<SharedPtr<Geometry> > > geometries_;
     /// Geometry centers.
     PODVector<Vector3> geometryCenters_;
+    /// Geometry distances.
+    PODVector<float> geometryDistances_;
     /// LOD levels.
     PODVector<unsigned> lodLevels_;
     /// Materials.

+ 21 - 21
Engine/Graphics/View.cpp

@@ -448,7 +448,7 @@ void View::GetBatches()
                     for (unsigned l = 0; l < numBatches; ++l)
                     {
                         Batch shadowBatch;
-                        drawable->GetBatch(shadowFrame_, l, shadowBatch);
+                        drawable->GetBatch(shadowBatch, shadowFrame_, l);
                         
                         Technique* tech = GetTechnique(drawable, shadowBatch.material_);
                         if (!shadowBatch.geometry_ || !tech)
@@ -522,7 +522,7 @@ void View::GetBatches()
             for (unsigned j = 0; j < numBatches; ++j)
             {
                 Batch baseBatch;
-                drawable->GetBatch(frame_, j, baseBatch);
+                drawable->GetBatch(baseBatch, frame_, j);
                 
                 Technique* tech = GetTechnique(drawable, baseBatch.material_);
                 if (!baseBatch.geometry_ || !tech)
@@ -540,7 +540,7 @@ void View::GetBatches()
                 // Fill the rest of the batch
                 baseBatch.camera_ = camera_;
                 baseBatch.zone_ = GetZone(drawable);
-                baseBatch.hasPriority_ = true;
+                baseBatch.isBase_ = true;
                 
                 Pass* pass = 0;
                 
@@ -592,7 +592,7 @@ void View::GetLitBatches(Drawable* drawable, LightBatchQueue& lightQueue)
     for (unsigned i = 0; i < numBatches; ++i)
     {
         Batch litBatch;
-        drawable->GetBatch(frame_, i, litBatch);
+        drawable->GetBatch(litBatch, frame_, i);
         
         Technique* tech = GetTechnique(drawable, litBatch.material_);
         if (!litBatch.geometry_ || !tech)
@@ -606,7 +606,7 @@ void View::GetLitBatches(Drawable* drawable, LightBatchQueue& lightQueue)
             pass = tech->GetPass(PASS_LITBASE);
             if (pass)
             {
-                litBatch.hasPriority_ = true;
+                litBatch.isBase_ = true;
                 drawable->SetBasePass(i);
             }
         }
@@ -754,7 +754,7 @@ void View::UpdateOccluders(PODVector<Drawable*>& occluders, Camera* camera)
             
             for (unsigned j = 0; j < batches; ++j)
             {
-                occluder->GetBatch(frame_, j, tempBatch);
+                occluder->GetBatch(tempBatch, frame_, j);
                 if (tempBatch.geometry_)
                     totalTriangles += tempBatch.geometry_->GetIndexCount() / 3;
             }
@@ -1616,21 +1616,21 @@ void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
     graphics_->SetScissorTest(false);
     graphics_->SetStencilTest(false);
     
-    // Priority instanced
-    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedPriorityBatchGroups_.Begin(); i !=
-        queue.sortedPriorityBatchGroups_.End(); ++i)
+    // Base instanced
+    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBaseBatchGroups_.Begin(); i !=
+        queue.sortedBaseBatchGroups_.End(); ++i)
     {
         BatchGroup* group = *i;
         group->Draw(graphics_, renderer_);
     }
-    // Priority non-instanced
-    for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
+    // Base non-instanced
+    for (PODVector<Batch*>::ConstIterator i = queue.sortedBaseBatches_.Begin(); i != queue.sortedBaseBatches_.End(); ++i)
     {
         Batch* batch = *i;
         batch->Draw(graphics_, renderer_);
     }
     
-    // Non-priority instanced
+    // Non-base instanced
     for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBatchGroups_.Begin(); i != queue.sortedBatchGroups_.End(); ++i)
     {
         BatchGroup* group = *i;
@@ -1638,13 +1638,13 @@ void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
             OptimizeLightByScissor(group->lightQueue_->light_);
         group->Draw(graphics_, renderer_);
     }
-    // Non-priority non-instanced
+    // Non-base non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)
     {
         Batch* batch = *i;
         if (useScissor)
         {
-            if (!batch->hasPriority_ && batch->lightQueue_)
+            if (!batch->isBase_ && batch->lightQueue_)
                 OptimizeLightByScissor(batch->lightQueue_->light_);
             else
                 graphics_->SetScissorTest(false);
@@ -1658,15 +1658,15 @@ void View::RenderLightBatchQueue(const BatchQueue& queue, Light* light)
     graphics_->SetScissorTest(false);
     graphics_->SetStencilTest(false);
     
-    // Priority instanced
-    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedPriorityBatchGroups_.Begin(); i !=
-        queue.sortedPriorityBatchGroups_.End(); ++i)
+    // Base instanced
+    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBaseBatchGroups_.Begin(); i !=
+        queue.sortedBaseBatchGroups_.End(); ++i)
     {
         BatchGroup* group = *i;
         group->Draw(graphics_, renderer_);
     }
-    // Priority non-instanced
-    for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
+    // Base non-instanced
+    for (PODVector<Batch*>::ConstIterator i = queue.sortedBaseBatches_.Begin(); i != queue.sortedBaseBatches_.End(); ++i)
     {
         Batch* batch = *i;
         batch->Draw(graphics_, renderer_);
@@ -1676,13 +1676,13 @@ void View::RenderLightBatchQueue(const BatchQueue& queue, Light* light)
     OptimizeLightByStencil(light);
     OptimizeLightByScissor(light);
     
-    // Non-priority instanced
+    // Non-base instanced
     for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBatchGroups_.Begin(); i != queue.sortedBatchGroups_.End(); ++i)
     {
         BatchGroup* group = *i;
         group->Draw(graphics_, renderer_);
     }
-    // Non-priority non-instanced
+    // Non-base non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)
     {
         Batch* batch = *i;

+ 1 - 1
Engine/Math/Vector2.cpp

@@ -31,7 +31,7 @@ const Vector2 Vector2::LEFT(-1.0f, 0.0f);
 const Vector2 Vector2::RIGHT(1.0f, 0.0f);
 const Vector2 Vector2::UP(0.0f, 1.0f);
 const Vector2 Vector2::DOWN(0.0f, -1.0f);
-const Vector2 Vector2::UNITY(1.0f, 1.0f);
+const Vector2 Vector2::ONE(1.0f, 1.0f);
 
 const IntVector2 IntVector2::ZERO(0, 0);
 

+ 1 - 1
Engine/Math/Vector2.h

@@ -203,7 +203,7 @@ public:
     /// (0,-1) vector.
     static const Vector2 DOWN;
     /// (1,1) vector.
-    static const Vector2 UNITY;
+    static const Vector2 ONE;
 };
 
 /// Multiply Vector2 with a scalar

+ 1 - 1
Engine/Math/Vector3.cpp

@@ -33,7 +33,7 @@ const Vector3 Vector3::UP(0.0f, 1.0f, 0.0f);
 const Vector3 Vector3::DOWN(0.0f, -1.0f, 0.0f);
 const Vector3 Vector3::FORWARD(0.0f, 0.0f, 1.0f);
 const Vector3 Vector3::BACK(0.0f, 0.0f, -1.0f);
-const Vector3 Vector3::UNITY(1.0f, 1.0f, 1.0f);
+const Vector3 Vector3::ONE(1.0f, 1.0f, 1.0f);
 
 String Vector3::ToString() const
 {

+ 1 - 1
Engine/Math/Vector3.h

@@ -239,7 +239,7 @@ public:
     /// (0,0,-1) vector.
     static const Vector3 BACK;
     /// (1,1,1) vector.
-    static const Vector3 UNITY;
+    static const Vector3 ONE;
 };
 
 /// Multiply Vector3 with a scalar.

+ 1 - 1
Engine/Math/Vector4.cpp

@@ -27,7 +27,7 @@
 #include <cstdio>
 
 const Vector4 Vector4::ZERO(0.0f, 0.0f, 0.0f, 0.0f);
-const Vector4 Vector4::UNITY(1.0f, 1.0f, 1.0f, 1.0f);
+const Vector4 Vector4::ONE(1.0f, 1.0f, 1.0f, 1.0f);
 
 String Vector4::ToString() const
 {

+ 1 - 1
Engine/Math/Vector4.h

@@ -186,7 +186,7 @@ public:
     /// Zero vector.
     static const Vector4 ZERO;
     /// (1,1,1) vector.
-    static const Vector4 UNITY;
+    static const Vector4 ONE;
 };
 
 /// Multiply Vector4 with a scalar.

+ 3 - 3
Engine/Physics/CollisionShape.cpp

@@ -302,12 +302,12 @@ CollisionShape::CollisionShape(Context* context) :
     Component(context),
     geometry_(0),
     shapeType_(SHAPE_NONE),
-    size_(Vector3::UNITY),
+    size_(Vector3::ONE),
     thickness_(0.0f),
     lodLevel_(0),
     position_(Vector3::ZERO),
     rotation_(Quaternion::IDENTITY),
-    geometryScale_(Vector3::UNITY),
+    geometryScale_(Vector3::ONE),
     collisionLayer_(M_MAX_UNSIGNED),
     collisionMask_(M_MAX_UNSIGNED),
     friction_(DEFAULT_FRICTION),
@@ -330,7 +330,7 @@ void CollisionShape::RegisterObject(Context* context)
     context->RegisterFactory<CollisionShape>();
     
     ENUM_ATTRIBUTE(CollisionShape, "Shape Type", shapeType_, typeNames, SHAPE_NONE, AM_DEFAULT);
-    ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Size", size_, Vector3::UNITY, AM_DEFAULT);
+    ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Size", size_, Vector3::ONE, AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Offset Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(CollisionShape, VAR_QUATERNION, "Offset Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);

+ 3 - 3
Engine/Physics/CollisionShape.h

@@ -115,11 +115,11 @@ public:
     /// %Set as a capsule.
     void SetCapsule(float diameter, float height, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
     /// %Set as a triangle mesh.
-    void SetTriangleMesh(Model* model, unsigned lodLevel, const Vector3& size = Vector3::UNITY, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
+    void SetTriangleMesh(Model* model, unsigned lodLevel, const Vector3& size = Vector3::ONE, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
     /// %Set as a heightfield.
-    void SetHeightfield(Model* model, unsigned xPoints, unsigned zPoints, float thickness, unsigned lodLevel, const Vector3& size = Vector3::UNITY, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
+    void SetHeightfield(Model* model, unsigned xPoints, unsigned zPoints, float thickness, unsigned lodLevel, const Vector3& size = Vector3::ONE, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
     /// %Set as a convex hull (internally an ODE trimesh as well.)
-    void SetConvexHull(Model* model, float skinWidth, unsigned lodLevel, const Vector3& size = Vector3::UNITY, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
+    void SetConvexHull(Model* model, float skinWidth, unsigned lodLevel, const Vector3& size = Vector3::ONE, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
     /// %Set offset position.
     void SetPosition(const Vector3& position);
     /// %Set rotation.

+ 2 - 2
Engine/Physics/RigidBody.cpp

@@ -459,13 +459,13 @@ void RigidBody::PostStep(float t, HashSet<RigidBody*>& processedBodies)
         if (!node_->IsSmoothed())
         {
             Matrix3x4 newTransform(parent->GetWorldTransform().Inverse() * Matrix3x4(previousPosition_.Lerp(currentPosition, t),
-                previousRotation_.Slerp(currentRotation, t), Vector3::UNITY));
+                previousRotation_.Slerp(currentRotation, t), Vector3::ONE));
             node_->SetTransform(newTransform.Translation(), newTransform.Rotation());
         }
         else
         {
             Matrix3x4 newTransform(parent->GetWorldTargetTransform().Inverse() * Matrix3x4(currentPosition, currentRotation,
-                Vector3::UNITY));
+                Vector3::ONE));
             node_->SetTransform(newTransform.Translation(), newTransform.Rotation());
         }
     }

+ 2 - 2
Engine/Scene/Node.cpp

@@ -44,7 +44,7 @@ Node::Node(Context* context) :
     owner_(0),
     position_(Vector3::ZERO),
     rotation_(Quaternion::IDENTITY),
-    scale_(Vector3::UNITY),
+    scale_(Vector3::ONE),
     worldTransform_(Matrix3x4::IDENTITY),
     targetPosition_(Vector3::ZERO),
     targetRotation_(Quaternion::IDENTITY),
@@ -72,7 +72,7 @@ void Node::RegisterObject(Context* context)
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_STRING, "Name", GetName, SetName, String, String(), AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_QUATERNION, "Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE);
-    REF_ACCESSOR_ATTRIBUTE(Node, VAR_VECTOR3, "Scale", GetScale, SetScale, Vector3, Vector3::UNITY, AM_DEFAULT);
+    REF_ACCESSOR_ATTRIBUTE(Node, VAR_VECTOR3, "Scale", GetScale, SetScale, Vector3, Vector3::ONE, AM_DEFAULT);
     ATTRIBUTE(Node, VAR_VARIANTMAP, "Variables", vars_, VariantMap(), AM_FILE); // Network replication of vars uses custom data
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_BUFFER, "Network Rotation", GetNetRotationAttr, SetNetRotationAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_LATESTDATA | AM_NOEDIT);
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_BUFFER, "Network Parent Node", GetNetParentAttr, SetNetParentAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_NOEDIT);

+ 1 - 1
Engine/Scene/Scene.cpp

@@ -77,7 +77,7 @@ void Scene::RegisterObject(Context* context)
     REF_ACCESSOR_ATTRIBUTE(Scene, VAR_STRING, "Name", GetName, SetName, String, String(), AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(Scene, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
     REF_ACCESSOR_ATTRIBUTE(Scene, VAR_QUATERNION, "Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE);
-    REF_ACCESSOR_ATTRIBUTE(Scene, VAR_VECTOR3, "Scale", GetScale, SetScale, Vector3, Vector3::UNITY, AM_DEFAULT);
+    REF_ACCESSOR_ATTRIBUTE(Scene, VAR_VECTOR3, "Scale", GetScale, SetScale, Vector3, Vector3::ONE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Scene, VAR_FLOAT, "Smoothing Constant", GetSmoothingConstant, SetSmoothingConstant, float, DEFAULT_SMOOTHING_CONSTANT, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Scene, VAR_FLOAT, "Snap Threshold", GetSnapThreshold, SetSnapThreshold, float, DEFAULT_SNAP_THRESHOLD, AM_DEFAULT);
     ATTRIBUTE(Scene, VAR_INT, "Next Replicated Node ID", replicatedNodeID_, FIRST_REPLICATED_ID, AM_FILE | AM_NOEDIT);

+ 1 - 1
Tools/AssetImporter/AssetImporter.cpp

@@ -958,7 +958,7 @@ void BuildAndSaveAnimations(OutModel& model)
                 kf.time_ = 0.0f;
                 kf.position_ = Vector3::ZERO;
                 kf.rotation_ = Quaternion::IDENTITY;
-                kf.scale_ = Vector3::UNITY;
+                kf.scale_ = Vector3::ONE;
                 
                 // Get time for the keyframe
                 if (track.channelMask_ & CHANNEL_POSITION && k < channel->mNumPositionKeys)

+ 1 - 1
Tools/OgreImporter/OgreImporter.cpp

@@ -168,7 +168,7 @@ void LoadSkeleton(const String& skeletonFileName)
             bones_[index].parentIndex_ = index; // Fill in the correct parent later
             bones_[index].bindPosition_ = pos;
             bones_[index].bindRotation_ = rot;
-            bones_[index].bindScale_ = Vector3::UNITY;
+            bones_[index].bindScale_ = Vector3::ONE;
             bones_[index].collisionMask_ = 0;
             bones_[index].radius_ = 0.0f;