#include "SceneEntity.h" #include "Geometry.h" #include "Material.h" #include "RenderState.h" #include "Shape.h" #include "Transform3.h" #include "Camera.h" #include "glInterface.h" using namespace std; namespace CHCDemoEngine { int sCurrentId = 0; bool SceneEntity::sUseLODs = true; int SceneEntity::sCurrentVisibleId = -1; SceneEntity::SceneEntity(Transform3 *trafo): mTransform(trafo), mCurrentLODLevel(0), mLODLastUpdated(-1), mId(sCurrentId ++), mVisibleId(0) { mBox.Initialize(); } SceneEntity::~SceneEntity() { } void SceneEntity::UpdateLODs(const Vector3 &viewPoint) { mCurrentLODLevel = 0; if (!sUseLODs) return; const Vector3 pos = GetWorldCenter(); const float dist = SqrDistance(pos, viewPoint); // note: we assume that lods are ordered from smallest distance to largest const int l = (int)mLODLevels.size(); for (int i = 0; i < l; ++ i) { if (mLODLevels[i].GetSquaredDistance() > dist) break; mCurrentLODLevel = i; } } int SceneEntity::GetCurrentLODLevel() { if (mLODLastUpdated != LODLevel::sFrameId) { mLODLastUpdated = LODLevel::sFrameId; UpdateLODs(LODLevel::sViewPoint); } return mCurrentLODLevel; } void SceneEntity::GetCurrentLODLevel(ShapeContainer::iterator &start, ShapeContainer::iterator &end) { if (mLODLastUpdated != LODLevel::sFrameId) { mLODLastUpdated = LODLevel::sFrameId; UpdateLODs(LODLevel::sViewPoint); } start = mLODLevels[mCurrentLODLevel].GetShapes().begin(); end = mLODLevels[mCurrentLODLevel].GetShapes().end(); } void SceneEntity::GetLODLevel(int level, ShapeContainer::iterator &start, ShapeContainer::iterator &end) { start = mLODLevels[level].GetShapes().begin(); end = mLODLevels[level].GetShapes().end(); } void SceneEntity::Render(RenderState *state) { ShapeContainer::iterator sit, sit_end; if (!mLODLevels.empty()) { GetCurrentLODLevel(sit, sit_end); } else { sit = mShapes.begin(); sit_end = mShapes.end(); } Prepare(state); for (; sit != sit_end; ++ sit) { (*sit)->Render(state, this); } mTransform->Unload(state); } void SceneEntity::AddShape(Shape *shape) { mShapes.push_back(shape); mBox.Include(shape->GetBoundingBox()); mCenter = mBox.Center(); } void SceneEntity::SetTransform(Transform3 *trafo) { mTransform = trafo; } void SceneEntity::SetLastRenderedFrame(int lastRenderedFrame) { mLastRenderedFrame = lastRenderedFrame; } int SceneEntity::GetLastRenderedFrame() const { return mLastRenderedFrame; } int SceneEntity::CountNumTriangles(int lodLevel) { int numTriangles = 0; ShapeContainer::iterator sit, sit_end; if (lodLevel == -1) lodLevel = GetCurrentLODLevel(); return mLODLevels[lodLevel].GetNumTriangles(); } AxisAlignedBox3 SceneEntity::GetWorldBoundingBox() const { if (mTransform->IsIdentity()) return mBox; Matrix4x4 mat = mTransform->GetMatrix(); return Transform(mBox, mat); } AxisAlignedBox3 SceneEntity::GetBoundingBox() const { return mBox; } Vector3 SceneEntity::GetWorldCenter() const { if (mTransform->IsIdentity()) return mCenter; return mTransform->GetMatrix() * mCenter; } void SceneEntity::Prepare(RenderState *state) { /*int id[] = {(mId / (255 * 255)) % 255, (mId / 255) % 255, mId % 255, 0}; GLfloat fogColor[4] = {(float)id[0] / 255.0f, (float)id[1] / 255.0f, (float)id[2] / 255.0f, .0f}; glFogfv(GL_FOG_COLOR, fogColor);*/ mTransform->Load(state); } AxisAlignedBox3 SceneEntity::ComputeBoundingBox(SceneEntity **entities, int numEntities) { AxisAlignedBox3 box; if (numEntities <= 0) { // no box => just initialize box.Initialize(); } else { box = entities[0]->GetWorldBoundingBox(); for (int i = 1; i < numEntities; ++ i) { box.Include(entities[i]->GetWorldBoundingBox()); } } return box; } AxisAlignedBox3 SceneEntity::ComputeBoundingBox(const SceneEntityContainer &entities) { AxisAlignedBox3 box; if (entities.empty()) { // no box => just initialize box.Initialize(); } else { box = entities[0]->GetWorldBoundingBox(); for (size_t i = 1; i < entities.size(); ++ i) { box.Include(entities[i]->GetWorldBoundingBox()); } } return box; } }