void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha) { BucketList::iterator bit; list<RAS_MeshSlot>::iterator mit; size_t size = 0, i = 0; /* Camera's near plane equation: pnorm.dot(point) + pval, * but we leave out pval since it's constant anyway */ const MT_Vector3 pnorm(cameratrans.getBasis()[2]); for (bit = buckets.begin(); bit != buckets.end(); ++bit) { SG_DList::iterator<RAS_MeshSlot> mit((*bit)->GetActiveMeshSlots()); for(mit.begin(); !mit.end(); ++mit) size++; } slots.resize(size); for (bit = buckets.begin(); bit != buckets.end(); ++bit) { RAS_MaterialBucket* bucket = *bit; RAS_MeshSlot* ms; // remove the mesh slot form the list, it culls them automatically for next frame while((ms = bucket->GetNextActiveMeshSlot())) { slots[i++].set(ms, bucket, pnorm); } } if(alpha) sort(slots.begin(), slots.end(), backtofront()); else sort(slots.begin(), slots.end(), fronttoback()); }
/* frees the bucket, only used when freeing scenes */ void RAS_BucketManager::RemoveMaterial(RAS_IPolyMaterial * mat) { BucketList::iterator bit, bitp; list<RAS_MeshSlot>::iterator mit; int i; for(i=0; i<m_SolidBuckets.size(); i++) { RAS_MaterialBucket *bucket = m_SolidBuckets[i]; if (mat == bucket->GetPolyMaterial()) { m_SolidBuckets.erase(m_SolidBuckets.begin()+i); delete bucket; i--; } } for(int i=0; i<m_AlphaBuckets.size(); i++) { RAS_MaterialBucket *bucket = m_AlphaBuckets[i]; if (mat == bucket->GetPolyMaterial()) { m_AlphaBuckets.erase(m_AlphaBuckets.begin()+i); delete bucket; i--; } } }
void KX_FontObject::AddMeshUser() { m_meshUser = new RAS_TextUser(m_pClient_info); // set the part of the mesh slot that never change float *fl = GetOpenGLMatrixPtr()->getPointer(); m_meshUser->SetMatrix(fl); RAS_BucketManager *bucketManager = GetScene()->GetBucketManager(); bool created = false; RAS_MaterialBucket *bucket = bucketManager->FindBucket(GetTextMaterial(), created); // If the material bucket is just created then we add a new mesh slot. if (created) { RAS_TexVertFormat format; format.uvSize = 1; format.colorSize = 1; bucket->NewMesh(NULL, NULL, format); } /* We copy the original mesh slot which is at the begin of the list, if it's not the case it * doesn't matter as the mesh slot are all similar exepted their mesh user pointer which is * set to NULL in copy. By copying instead of adding a mesh slot we reuse the same display * array bucket. */ RAS_MeshSlot *ms = bucket->CopyMesh(*bucket->msBegin()); ms->SetMeshUser(m_meshUser); ms->SetDeformer(NULL); m_meshUser->AddMeshSlot(ms); }
void RAS_BucketManager::RenderBasicBuckets(const MT_Transform& cameratrans, RAS_IRasterizer *rasty, RAS_BucketManager::BucketType bucketType) { BucketList& solidBuckets = m_buckets[bucketType]; for (BucketList::iterator bit = solidBuckets.begin(); bit != solidBuckets.end(); ++bit) { RAS_MaterialBucket *bucket = *bit; bucket->RenderMeshSlots(cameratrans, rasty); } }
void RAS_BucketManager::RenderSolidBuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { BucketList::iterator bit; rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { #if 1 RAS_MaterialBucket* bucket = *bit; RAS_MeshSlot* ms; // remove the mesh slot form the list, it culls them automatically for next frame while((ms = bucket->GetNextActiveMeshSlot())) { rendertools->SetClientObject(rasty, ms->m_clientObj); while (bucket->ActivateMaterial(cameratrans, rasty, rendertools)) bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *ms); // make this mesh slot culled automatically for next frame // it will be culled out by frustrum culling ms->SetCulled(true); } #else list<RAS_MeshSlot>::iterator mit; for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { if (mit->IsCulled()) continue; rendertools->SetClientObject(rasty, mit->m_clientObj); while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools)) (*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit); // make this mesh slot culled automatically for next frame // it will be culled out by frustrum culling mit->SetCulled(true); } #endif } /* this code draws meshes order front-to-back instead to reduce overdraw. * it turned out slower due to much material state switching, a more clever * algorithm might do better. */ #if 0 vector<sortedmeshslot> slots; vector<sortedmeshslot>::iterator sit; OrderBuckets(cameratrans, m_SolidBuckets, slots, false); for(sit=slots.begin(); sit!=slots.end(); ++sit) { rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); } #endif }
void RAS_BucketManager::ReleaseMaterials(RAS_IPolyMaterial *mat) { BucketList& buckets = m_buckets[ALL_BUCKET]; for (BucketList::iterator it = buckets.begin(), end = buckets.end(); it != end; ++it) { RAS_MaterialBucket *bucket = *it; if (mat == NULL || (mat == bucket->GetPolyMaterial())) { bucket->GetPolyMaterial()->ReleaseMaterial(); } } }
void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat) { BucketList& buckets = m_buckets[ALL_BUCKET]; for (BucketList::iterator it = buckets.begin(), end = buckets.end(); it != end; ++it) { RAS_MaterialBucket *bucket = *it; if (bucket->GetPolyMaterial() != mat && mat) { continue; } RAS_DisplayArrayBucketList& displayArrayBucketList = bucket->GetDisplayArrayBucketList(); for (RAS_DisplayArrayBucketList::iterator dit = displayArrayBucketList.begin(), dend = displayArrayBucketList.end(); dit != dend; ++dit) { (*dit)->DestructStorageInfo(); } } }
RAS_MaterialBucket *RAS_BucketManager::FindBucket(RAS_IPolyMaterial *material, bool &bucketCreated) { bucketCreated = false; BucketList& buckets = m_buckets[ALL_BUCKET]; for (BucketList::iterator it = buckets.begin(), end = buckets.end(); it != end; ++it) { RAS_MaterialBucket *bucket = *it; if (bucket->GetPolyMaterial() == material) { return bucket; } } RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; const bool useinstancing = material->UseInstancing(); if (!material->OnlyShadow()) { if (material->IsAlpha()) { if (material->IsAlphaDepth()) { m_buckets[useinstancing ? ALPHA_DEPTH_INSTANCING_BUCKET : ALPHA_DEPTH_BUCKET].push_back(bucket); } else { m_buckets[useinstancing ? ALPHA_INSTANCING_BUCKET : ALPHA_BUCKET].push_back(bucket); } } else { m_buckets[useinstancing ? SOLID_INSTANCING_BUCKET : SOLID_BUCKET].push_back(bucket); } } if (material->CastsShadows()) { if (material->IsAlphaShadow()) { m_buckets[useinstancing ? ALPHA_SHADOW_INSTANCING_BUCKET : ALPHA_SHADOW_BUCKET].push_back(bucket); } else { m_buckets[useinstancing ? SOLID_SHADOW_INSTANCING_BUCKET : SOLID_SHADOW_BUCKET].push_back(bucket); } } if (material->IsText()) { m_buckets[TEXT_BUCKET].push_back(bucket); } // Used to free the bucket. m_buckets[ALL_BUCKET].push_back(bucket); return bucket; }
/* frees the bucket, only used when freeing scenes */ void RAS_BucketManager::RemoveMaterial(RAS_IPolyMaterial *mat) { for (unsigned short i = 0; i < NUM_BUCKET_TYPE; ++i) { BucketList& buckets = m_buckets[i]; for (BucketList::iterator it = buckets.begin(); it != buckets.end();) { RAS_MaterialBucket *bucket = *it; if (mat == bucket->GetPolyMaterial()) { it = buckets.erase(it); if (i == ALL_BUCKET) { delete bucket; } } else { ++it; } } } }
RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { BucketList::iterator it; bucketCreated = false; for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) if (*(*it)->GetPolyMaterial() == *material) return *it; for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) if (*(*it)->GetPolyMaterial() == *material) return *it; RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else m_SolidBuckets.push_back(bucket); return bucket; }
void RAS_BucketManager::RenderSortedBuckets(const MT_Transform& cameratrans, RAS_IRasterizer *rasty, RAS_BucketManager::BucketType bucketType) { std::vector<sortedmeshslot> slots; std::vector<sortedmeshslot>::iterator sit; OrderBuckets(cameratrans, bucketType, slots, true, rasty); // Discard if there's no mesh slots. if (slots.size() == 0) { return; } // The last display array and material bucket used to avoid double calls. RAS_DisplayArrayBucket *lastDisplayArrayBucket = NULL; RAS_MaterialBucket *lastMaterialBucket = NULL; bool matactivated = false; for (sit = slots.begin(); sit != slots.end(); ++sit) { RAS_MaterialBucket *bucket = sit->m_bucket; RAS_DisplayArrayBucket *displayArrayBucket = sit->m_ms->m_displayArrayBucket; /* Unbind display array here before unset material to use the proper * number of attributs in storage unbind since this variable is * global and mutated by all material during its activation. */ if (displayArrayBucket != lastDisplayArrayBucket && lastDisplayArrayBucket) { rasty->UnbindPrimitives(lastDisplayArrayBucket); } if (bucket != lastMaterialBucket) { if (matactivated) { lastMaterialBucket->DesactivateMaterial(rasty); } matactivated = bucket->ActivateMaterial(rasty); lastMaterialBucket = bucket; } /* Bind the new display array here after material activation to use * proper attributs numbers, same as display array unbind before. */ if (displayArrayBucket != lastDisplayArrayBucket) { rasty->BindPrimitives(displayArrayBucket); lastDisplayArrayBucket = displayArrayBucket; } bucket->RenderMeshSlot(cameratrans, rasty, sit->m_ms); } // Always unbind VBO or VA before unset the material to use the correct material attributs. rasty->UnbindPrimitives(lastDisplayArrayBucket); if (matactivated) { lastMaterialBucket->DesactivateMaterial(rasty); } }